【re】 watevrCTF2019_Repyc

這題給了個pyc。先用uncompyle反編譯成py。

uncompyle6 3nohtyp.pyc >>sss.py

打開,然後驚了。

# uncompyle6 version 3.6.0
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.8.0 (default, Oct 23 2019, 18:51:26) 
# [GCC 9.2.0]
# Embedded file name: circ.py
# Compiled at: 2019-12-14 02:29:55
# Size of source mod 2**32: 5146 bytes= 0= ~* ~佤
俴 =+def():= 佤
    굿 = 佤
    괠 = [] *** (*)= [] * 100= []
    while[][] != '듃':=[][].lower()=[][:]
        #print(괠 )
        #print(궓 )
        if== '뉃':[[]] =[[]] +[[]]
        elif== '렀':[[]] =[[]] ^[[]]
        elif== '렳':[[]] =[[]] -[[]]
        elif== '냃':[[]] =[[]] *[[]]
        elif== '뢯':[[]] =[[]] /[[]]
        elif== '륇':[[]] =[[]] &[[]]
        elif== '맳':[[]] =[[]] |[[]]
        elif== '괡':[[]] =[[]]
        elif== '뫇':[[]] =[[]]
        elif== '꼖':[[]] =[]
        elif== '뫻':[[]] =[[]]
        elif== '딓':[[]] =[[]]
        elif== '댒':[[]] =elif== '묇':[[]] =elif== '묟':[[]] = input([[]])
        elif== '꽺':[[]] = input([[]])
        elif== '돯':
            print([[]])
        elif== '뭗':
            print([[]])
        elif== '뭿':=[[]]
        elif== '뮓':=[[]]
        elif== '뮳':=.pop()
        elif== '믃':
            if[[]] >[[]]:=[].append()
                continue
            elif== '꽲':[7] =for i in range(len([[]])):
                    if[[]] !=[[]]:[7] = 侰
                        굴 =[[]].append()

            elif== '꾮':= ''
                for i in range(len([[]])):+= chr(ord([[]][i]) ^[[]])

                print()[[]] =elif== '꿚':= ''
                for i in range(len([[]])):+= chr(ord([[]][i]) -[[]])[[]] =elif== '떇':
                if[[]] >[[]]:=[[]].append()
                    continue
                elif== '뗋':
                    if[[]] >[[]]:=[[]].append()
                        continue
                    elif== '똷':
                        if[[]] ==[[]]:=[].append()
                            continue
                        elif== '뚫':
                            if[[]] ==[[]]:=[[]].append()
                                continue
                            elif== '띇':
                                if[[]] ==[[]]:=[[]].append()
                                    continue+= 侰


䯂([
 [
  '꼖',, 'Authentication token: '],
 [
  '꽺',,],
 [
  '꼖', 6, 'á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'],
 [
  '꼖',,** (3 *+) -** (+)],
 [
  '꼖', 4, 15],
 [
  '꼖', 3,],
 [
  '냃',,, 3],
 [
  '뉃',,, 4],
 [
  '괡',,],
 [
  '댒', 3],
 [
  '꾮', 6, 3],
 [
  '꼖',, 'Thanks.'],
 [
  '꼖',, 'Authorizing access...'],
 [
  '돯',],
 [
  '딓',,],
 [
  '꾮',,],
 [
  '꿚',, 4],
 [
  '꼖', 5, 19],
 [
  '꽲',, 6, 5],
 [
  '돯',],
 [
  '듃'],
 [
  '꼖',, 'Access denied!'],
 [
  '돯',],
 [
  '듃']])
# okay decompiling 3nohtyp.pyc

發現了很多非ascii字符,由於是python3,所以是可以有非ascii字符的,如:

In [2]: chr(256)                                                                                                                        
Out[2]: 'Ā'

In [3]: chr(243)                                                                                                                        
Out[3]: 'ó'

In [4]: chr(336)                                                                                                                        
Out[4]: 'Ő'

先不管編碼,看這個py,有一個函數,下面是函數調用,函數裏都是if語句,還有±*/&|這些操作,很像是一個VM,那麼下面的函數調用的列表參數就是這個VM的代碼。
嘗試修改這個py文件,用ascii字符進行替換,讓其可讀,刪除一些沒有執行到的代碼以及反編譯時候可能存在的錯誤。

# uncompyle6 version 3.6.0
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.8.0 (default, Oct 23 2019, 18:51:26) 
# [GCC 9.2.0]
# Embedded file name: circ.py
# Compiled at: 2019-12-14 02:29:55
# Size of source mod 2**32: 5146 bytes
a = 0
b = 1
c = 2

def fun1 (arg):
    A= a
    M= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    C= [a] * 100
    K= []
    while arg[A][a] != '12':
        #print(M)
        opcode= arg[A][a].lower()
        opn = arg[A][b:]
        #print(opn)
        if opcode== '4':
            M [opn[a]] = M [opn[b]] + M[opn[c]]
        elif opcode== '3':
            M [opn[a]] = M [opn[b]] * M[opn[c]]
        elif opcode== '5':
            M [opn[a]] = M [opn[a]]
        elif opcode== '1':
            M[opn[a]] = opn[b]
        elif opcode== '11':
            M[opn[a]] = C[opn[b]]
        elif opcode== '6':
            M[opn[a]] = a
        elif opcode== '2':
            C[opn[a]] = input(M[opn[b]])
        elif opcode== '10':
            print(M[opn[a]])
        elif opcode== '9':
            M[7] = a
            for i in range(len(M[opn[a]])):
                print( M[opn[a]], M[opn[b]])
                if M[opn[a]] != M[opn[b]]:
                    M[7] = b
                    A= M[opn[c]]
                    K.append(A)

        elif opcode== '7':
            s= ''
            for i in range(len(M[opn[a]])):
                s+= chr(ord(M[opn[a]][i]) ^ M[opn[b]])
            print(s)
            M[opn[a]] = s
        elif opcode== '8':
            s= ''
            for i in range(len(M[opn[a]])):
                #print(M[opn[a]][i],M[opn[b]])
                s+= chr(ord(M[opn[a]][i]) - M[opn[b]])
            M[opn[a]] = s

        A+= b


fun1([
 [
  '1', 0, 'Authentication token: '],
 [
  '2', 0, 0],
 [
  '1', 6, 'á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'],
 [
  '1', 2, c ** (3 * c + b) - c ** (c + b)],
 [
  '1', 4, 15],
 [
  '1', 3, b],
 [
  '3', 2, 2, 3],
 [
  '4', c, c, 4],
 [
  '5', a, c],
 [
  '6', 3],
 [
  '7', 6, 3],
 [
  '1', 0, 'Thanks.'],
 [
  '1', 1, 'Authorizing access...'],
 [
  '10', 0],
 [
  '11', a, a],
 [
  '7', a, 2],
 [
  '8', a, 4],
 [
  '1', 5, 19],
 [
  '9', 0, 6, 5], 
 [
  '10', 1],
 [
  '12'],
 [
  '1', b, 'Access denied!'],
 [
  '10', 1],
 [
  '12']])
# okay decompiling 3nohtyp.pyc

接下來開始分析虛擬機,每個opcode handler都比較簡單,直接給出分析結果。

操作碼分析如下

opcode    operation
1         mov M[op1] op2
2		  read M[op1] stdin
3		  M[op1]=M[op2]+M[op3]
4		  M[op1]=M[op2]*M[op3]
5		  M[op1]=M[op1]
6 		  M[op1]=0
7         M[op1]中每個字符異或M[op2]
8         M[op1]中每個字符減去M[op2]
9         jnp M[op1] M[op2]
10        write M[op1] stdout
11        mov M[op1] C[op2]
12        exit

代碼序列分析後發現就是將輸入和某值異或再和某值(可通過動態調試得到)相減之後與字符串比較,相同輸出Authorizing access…不同輸出Access denied!

寫逆算法

s='á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'
flag=''
for i in range(len(s)):
    flag+=chr((ord(s[i])+15)^135)
print(flag)

這題難點還是在對這種非常陌生的編碼處理上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章