본문 바로가기

Dreamhack

[Dreamhack] pybycodets

반응형

Description

이게 Python....?

 

Blitz CTF 문제였다.


Write-up

Step1) 문제 파일 압축을 풀어보면 총 3개의 파일이 존재한다. main.txt와 hard2rev.txt에는 바이트 코드 형식으로 작성되어 있다.

(❓바이트 코드 : 고급 언어로 작성된 소스 코드를 가상머신이 이해할 수 있는 중간 코드로 컴파일한 것을 말한다.)

// main.txt
  4           0 LOAD_CONST               1 (** FLAG censored **)
              2 STORE_FAST               0 (v1)    

  5           4 LOAD_GLOBAL              0 (list)  
              6 LOAD_FAST                0 (v1)    
              8 LOAD_METHOD              1 (encode)
             10 CALL_METHOD              0
             12 CALL_FUNCTION            1
             14 STORE_FAST               0 (v1)    

  6          16 LOAD_GLOBAL              2 (range) 
             18 LOAD_CONST               2 (0)     
             20 LOAD_GLOBAL              3 (len)   
             22 LOAD_FAST                0 (v1)    
             24 CALL_FUNCTION            1
             26 CALL_FUNCTION            2
             28 GET_ITER
        >>   30 FOR_ITER                20 (to 52) 
             32 STORE_FAST               1 (i)     

  7          34 LOAD_FAST                0 (v1)
             36 LOAD_FAST                1 (i)
             38 DUP_TOP_TWO
             40 BINARY_SUBSCR
             42 LOAD_FAST                1 (i)
             44 INPLACE_XOR
             46 ROT_THREE
             48 STORE_SUBSCR
             50 JUMP_ABSOLUTE           30

  8     >>   52 LOAD_GLOBAL              4 (hard2rev)
             54 LOAD_FAST                0 (v1)
             56 CALL_FUNCTION            1
             58 STORE_FAST               0 (v1)

  9          60 LOAD_GLOBAL              5 (print)
             62 LOAD_FAST                0 (v1)
             64 CALL_FUNCTION            1
             66 POP_TOP
             68 LOAD_CONST               0 (None)
             70 RETURN_VALUE
 // hard2rev.txt
 12           0 LOAD_GLOBAL              0 (range)
              2 LOAD_GLOBAL              1 (len)  
              4 LOAD_FAST                0 (v1)   
              6 CALL_FUNCTION            1        
              8 CALL_FUNCTION            1        
             10 GET_ITER
        >>   12 FOR_ITER                50 (to 64)
             14 STORE_FAST               1 (j)    

 13          16 LOAD_FAST                0 (v1)   
             18 LOAD_FAST                1 (j)    
             20 BINARY_SUBSCR
             22 LOAD_CONST               1 (36)   
             24 BINARY_ADD
             26 LOAD_FAST                0 (v1)   
             28 LOAD_FAST                1 (j)    
             30 STORE_SUBSCR

 14          32 LOAD_GLOBAL              0 (range)
             34 LOAD_FAST                1 (j)    
             36 LOAD_CONST               2 (2)
             38 BINARY_FLOOR_DIVIDE
             40 CALL_FUNCTION            1
             42 GET_ITER
        >>   44 FOR_ITER                16 (to 62)
             46 STORE_FAST               2 (x)

 15          48 LOAD_GLOBAL              2 (list)
             50 LOAD_GLOBAL              3 (reversed)
             52 LOAD_FAST                0 (v1)
             54 CALL_FUNCTION            1
             56 CALL_FUNCTION            1
             58 STORE_FAST               0 (v1)
             60 JUMP_ABSOLUTE           44
        >>   62 JUMP_ABSOLUTE           12

 16     >>   64 LOAD_FAST                0 (v1)
             66 RETURN_VALUE
// output.txt
[140, 109, 157, 112, 179, 126, 140, 110, 179, 144, 121, 123, 189, 147, 155, 108, 199, 153, 155, 103, 185, 138, 91, 106]

 

 

Step2) 파이썬 바이트 코드를 역어셈블리해보면 아래와 같다.

# main.txt
v1 = "** FLAG censored **"
v1 = list(v1.encode())

for i in range(len(v1)):
    v1[i] ^= i  # 각 바이트에 인덱스 값을 XOR

v1 = hard2rev(v1)
print(v1)
# hard2rev.txt
def hard2rev(v1):
    for j in range(len(v1)):
        v1[j] = v1[j] + 36

        for x in range(j // 2):
            v1 = list(reversed(v1))  # 리스트를 뒤집음

    return v1

 

 

Step3) 위의 코드를 참고하여 output.txt에 적힌 숫자 리스트를 이용하여 역으로 복호화하는 코드를 작성했다. 이것을 통해 최종 FLAG 값을 얻을 수 있다.

# reverse_flag.py
# 1. hard2rev2 되돌리기
def reverse_hard2rev(v1):
	for j in reversed(range(len(v1))):
    	for _ in reversed(range(j //2)):
        	v1 = list(reversed(v1))
        v1[j] -= 36
    return v1

v1 = [140, 109, 157, 112, 179, 126, 140, 110, 179, 144, 121, 123, 189, 147, 155, 108, 199, 153, 155, 103, 185, 138, 91, 106]

# 1. hard2rev2 되돌리기
v1 = reverse_hard2rev(v1)

# 2. xor 되돌리기
for i in range(len(v1)):
	v1[i] ^= i
    
# 3. ASCII 문자로 변환
flag = ''.join(chr(c) for c in v1)

print("\nFLAG =", flag)

 


Flag

DH{so_nice_pybycodetes!}

반응형