Write-up/Reversing

[Dreamhack] Simple crack me 2

mameul 2024. 9. 27. 14:36
728x90

풀이

제공된 파일을 IDA로 실행시켰다.

correct가 출력되게 하는 부분을 찾아서 decompling 해줬다

코드를 살펴보면 32바이트 문자열을 s2에 받아서 8번의 함수연산을 통해 암호화한 다음, s2의 값과 비교하여 일치하면 correct가 나오는 것을 알 수 있다.  

unk_402008 = [
    0xF8, 0xE0, 0xE6, 0x9E, 0x7F, 0x32, 0x68, 0x31, 
    0x05, 0xDC, 0xA1, 0xAA, 0xAA, 0x09, 0xB3, 0xD8, 
    0x41, 0xF0, 0x36, 0x8C, 0xCE, 0xC7, 0xAC, 0x66, 
    0x91, 0x4C, 0x32, 0xFF, 0x05, 0xE0, 0xD9, 0x91
]

먼저 복호화해야하는 값인 s2 값 (=unk_402008)을 찾아 파이썬의 리스트 형태로 옮겨주었다.

그 다음 암호화 과정을 살펴보았다.

보면, sub_4011EF, sub_401263, sub_4012B0 함수가 반복되고 입력값들이 변하는 것을 알 수 있었다. 

sub_4011EF 함수를 살펴보면 a1의 바이트 값과 a2의 바이트 값을 XOR 하는 연산인 것을 알 수 있다. a2 값은 돌아가면서 사용되고 있다.

unk_402068 = [0xDE, 0xAD, 0xBE, 0xEF]  
unk_40206D = [0xFF, 0xAD, 0xDE]      
unk_402072 = [0x11, 0x33, 0x55, 0x77, 0x99, 0xBB, 0xDD]

 

a2 입력값으로 사용되는 바이트값을 찾아 리스트 형태로 옮겨주었다.

sub_401263 함수는 a1의 각 값에 a2 값을 더해주는 것을 알 수 있다.

sub_4012B0 함수는 a1의 각 값에 a2 값을 빼주는 것을 알 수 있다.

def crypt(a1):
    L1 = len(unk_402068)
    
    for i in range(32):
        a1[i] = (a1[i] ^ unk_402068[i % L1])%256
    ###  
    for i in range(32):
        a1[i] = (a1[i] + 31)%256
    ###    
    for i in range(32):
        a1[i] = (a1[i] - 90)%256
    ###    
    L2 = len(unk_40206D)
    
    for i in range(32):
        a1[i] = (a1[i] ^ unk_40206D[i % L2])%256
    ###
    for i in range(32):
        a1[i] = (a1[i] - 77)%256
    ###    
    for i in range(32):
        a1[i] = (a1[i] + 243)%256
    ###
    L3 = len(unk_402072)
    
    for i in range(32):
        a1[i] = (a1[i] ^ unk_402072[i % L3])%256 
    
    return a1

위의 암호화 과정을 하나의 파이썬 함수로 옮겼보고, 그 역과정으로 복호화 함수를 짜줬다.

def decrypt(a1):
    L3 = len(unk_402072)
    
    for i in range(32):
        a1[i] = (a1[i] ^ unk_402072[i % L3])%256 
    ### 
    for i in range(32):
        a1[i] = (a1[i] - 243)%256
    ###  
    for i in range(32):
        a1[i] = (a1[i] + 77)%256
    ### 
    L2 = len(unk_40206D)
    
    for i in range(32):
        a1[i] = (a1[i] ^ unk_40206D[i % L2])%256
    ###
    for i in range(32):
        a1[i] = (a1[i] + 90)%256
    ###
    for i in range(32):
        a1[i] = (a1[i] - 31)%256
    ###
    L1 = len(unk_402068)
    
    for i in range(32):
        a1[i] = (a1[i] ^ unk_402068[i % L1])%256
        
    return a1

print(decrypt(unk_402008))

unk_402008을 복호화한 값은 이렇게 나왔다.

복호화된 리스트를 아스키코드로 변환한 후 하나로 합쳐주는 코드를 추가하여 필요한 입력값을 얻을 수 있었다.