Rev/Write-up

Christmas CTF 2020 - lock

zooonique 2020. 12. 28. 22:03
반응형

처음에 dump파일이 주어진다.

 

Hxd나 메모장으로 해당파일을 열어보면 ARM 어셈블리어로 구성된 내용을 확인할 수 있다.

 

해당 dump파일을 변환하여 ELF파일로 바꿔서 아이다로 편하게 볼 수 있을까? 고민했지만, 실패했다.

 

정말 오랜만에 어셈블리어를 읽기시작했다. (STR과 LDR의 개념을 잘 익혀두는 것이 좋다.)

 

더보기

0000000000000c50 <main>:
 c50: a9be7bfd  stp x29, x30, [sp, #-32]! // 스택 공간 
 c54: 910003fd  mov x29, sp
 c58: d2800021 mov x1, #0x1                    // #1
 c5c: d2800260 mov x0, #0x13                   // #19
 c60: 97fffee0  bl 7e0 <calloc@plt>
 c64: f9000be0  str x0, [sp, #16]
 c68: 97ffff94  bl ab8 <sub_ab8>
 c6c: 97ffff51  bl 9b0 <sub_9b0>
 c70: f9000fe0  str x0, [sp, #24] // [sp+24]=return value
 c74: 97ffff3e  bl 96c <sub_96c> // 그냥 print
 c78: f9400be1  ldr x1, [sp, #16]
 c7c: 90000000  adrp x0, 0 <_init-0x760>
 c80: 9138a000  add x0, x0, #0xe28              // #0xe28 '%s'
 c84: 97fffeeb  bl 830 <__isoc99_scanf@plt>
 c88: f9400fe1  ldr x1, [sp, #24] // x1=fixed_value1
 c8c: f9400be0  ldr x0, [sp, #16]
 c90: 97ffffa8  bl b30 <sub_b30>
 c94: f9400be0  ldr x0, [sp, #16]
 c98: 97fffee2  bl 820 <free@plt>
 c9c: 52800000  mov w0, #0x0                    // #0
 ca0: a8c27bfd  ldp x29, x30, [sp], #32
 ca4: d65f03c0  ret

 

분석을 진행해보면, <sub_ab8>함수와 <sub_b30>함수가 중요하다.

 

더보기

0000000000000ab8 <sub_ab8>:
 ab8: a9be7bfd  stp x29, x30, [sp, #-32]!
 abc: 910003fd  mov x29, sp // x29=[sp]
 ac0: 52800103  mov w3, #0x8                    // w3=8
 ac4: 90000000  adrp x0, value0@page // x0=#value0 (주소)
 ac8: 9136e002  add x2, x0, value0@pageoff // x2=[value0]
 acc: 528007c1  mov w1, #0x3e                   // w1=#62
 ad0: 90000000  adrp x0, value1@page // x0 =#value1 (주소)
 ad4: 91372000  add x0, x0, value1@pageoff // x0 = [value1]
 ad8: 97ffffc9  bl 9fc <sub_9fc>
 adc: f9000fe0  str x0, [sp, #24]
 ae0: f9400fe0  ldr x0, [sp, #24]
 ae4: a8c27bfd  ldp x29, x30, [sp], #32
 ae8: d65f03c0  ret

 

<sub_ab8>함수는 <sub_9fc>에서 쓰이는 파라미터를 저장하고, 전달하는 내용이라고 인식하면 된다.

 

더보기

00000000000009fc <sub_9fc>:
 9fc: a9bc7bfd  stp x29, x30, [sp, #-64]!
 a00: 910003fd  mov x29, sp
 a04: f90017e0  str x0, [sp, #40] // [sp+40] = value1
 a08: b90027e1 str w1, [sp, #36] // [sp+36] = 62
 a0c: f9000fe2  str x2, [sp, #24] // [sp+24] = value0
 a10: b90023e3 str w3, [sp, #32] // [sp+32] = 8
 a14: b94027e0 ldr w0, [sp, #36] // w0 = [sp+36] #62
 a18: 11000400  add w0, w0, #0x1 // w0 = w0+1 #63
 a1c: 93407c00  sxtw x0, w0
 a20: 97ffff68  bl 7c0 <malloc@plt>
 a24: f9001fe0  str x0, [sp, #56] // [sp+56] = malloc size
 a28: b98027e0 ldrsw x0, [sp, #36] // x0 = [sp+36] #62
 a2c: f9401fe1  ldr x1, [sp, #56] // x1 = malloc size
 a30: 8b000020 add x0, x1, x0 // x0=x1+x0
 a34: 3900001f  strb wzr, [x0] // x0=0
 a38: b90037ff  str wzr, [sp, #52] // [sp+52]=0
 a3c: 14000018  b a9c <sub_9fc+0xa0>
 a40: b98037e0 ldrsw x0, [sp, #52] // x0 = [sp+52] #0 -> 1 -> 2 -> 3
 a44: f94017e1  ldr x1, [sp, #40] // x1 = [sp+40] #value1
 a48: 8b000020 add x0, x1, x0 // x0 = x1 +x0 #value1[i]   
 a4c: 39400002  ldrb w2, [x0] // w2 = x0 ------ value1 -> w2
=================================================================================================
 a50: b94037e0 ldr w0, [sp, #52] // w0 = [sp+52] #0 -> 1 -> 2 -> 3
 a54: b94023e1 ldr w1, [sp, #32] // w1 = [sp+32] #8 
 a58: 1ac10c03  sdiv w3, w0, w1 // w3 = w0/8
 a5c: b94023e1 ldr w1, [sp, #32]
 a60: 1b017c61 mul w1, w3, w1 // w1 = w3*8
 a64: 4b010000 sub w0, w0, w1 // w0 = w0-w1 ##### i%8
 a68: 93407c00  sxtw x0, w0 // x0 = w0
 a6c: f9400fe1  ldr x1, [sp, #24] // x1 = [sp+24] #value0
 a70: 8b000020 add x0, x1, x0 // x0 = x1+x0 #value0[i]
 a74: 39400001  ldrb w1, [x0] // w1 = [x0] ----- value0 -> w1
 a78: b98037e0 ldrsw x0, [sp, #52] // x0 = [sp+52] #0
 a7c: f9401fe3  ldr x3, [sp, #56] // x3 = [sp+56] #mallocsize
 a80: 8b000060 add x0, x3, x0 // x0 += x3
 a84: 4a010041  eor w1, w2, w1 // w1 = w2^w1
 a88: 12001c21  and w1, w1, #0xff
 a8c: 39000001  strb w1, [x0] // w1 = [x0]
 a90: b94037e0 ldr w0, [sp, #52] // w0 = [sp+52]
 a94: 11000400  add w0, w0, #0x1 // w0 = w0 + 1
 a98: b90037e0 str w0, [sp, #52] // [sp+52] = w0
 a9c: b94037e1 ldr w1, [sp, #52] // w1 = [sp+52]
 aa0: b94027e0 ldr w0, [sp, #36] // w0 = [sp+36]
 aa4: 6b00003f  cmp w1, w0
 aa8: 54fffccb  b.lt a40 <sub_9fc+0x44>  // b.tstop
 aac: f9401fe0  ldr x0, [sp, #56]
 ab0: a8c47bfd  ldp x29, x30, [sp], #64
 ab4: d65f03c0  ret

(주석에 대충 어떤식으로 돌아가는지 적어놨다.)

여기까지 내용은 value0와 value1을 xor해서 새로운 value1을 만드는 과정이다.

 

그 이후에는 main함수에서 <sub_9b0>를 통해 문자열을 복사하고, <sub_96c>를 통해 별의미없는 print를 해주고,

 

scanf로 입력을 받는다.

 

마지막으로 <sub_b30>을 확인해보면

 

더보기

0000000000000b30 <sub_b30>:
 b30: a9be7bfd  stp x29, x30, [sp, #-32]!
 b34: 910003fd  mov x29, sp
 b38: f9000fe0  str x0, [sp, #24] // x0 = key
 b3c: f9000be1  str x1, [sp, #16] // x1 = fixed_value1
 b40: f9400fe0  ldr x0, [sp, #24]
 b44: 91001800  add x0, x0, #0x6  
 b48: 39400001  ldrb w1, [x0] // w1 = key[6]
 b4c: f9400be0  ldr x0, [sp, #16]
 b50: 91003800  add x0, x0, #0xe  // fixed_value1[e]
 b54: 39400000  ldrb w0, [x0]
 b58: 6b00003f  cmp w1, w0  // key[6] = fixed_value1[0xe]
 b5c: 54000761  b.ne c48 <sub_b30+0x118>  // b.any
 b60: f9400fe0  ldr x0, [sp, #24]  
 b64: 91001000  add x0, x0, #0x4
 b68: 39400001  ldrb w1, [x0]  // w1 = key[4]
 b6c: f9400be0  ldr x0, [sp, #16]
 b70: 91000c00  add x0, x0, #0x3  // fixed_value[3]
 b74: 39400000  ldrb w0, [x0]
 b78: 6b00003f  cmp w1, w0  // key[4] = fixed_value1[0x3]
 b7c: 54000661  b.ne c48 <sub_b30+0x118>  // b.any
 b80: f9400fe0  ldr x0, [sp, #24]
 b84: 91000c00  add x0, x0, #0x3
 b88: 39400001  ldrb w1, [x0]
 b8c: f9400be0  ldr x0, [sp, #16]
 b90: 91002800  add x0, x0, #0xa
 b94: 39400000  ldrb w0, [x0]
 b98: 6b00003f  cmp w1, w0  //key[3] = fixed_value1[0xa]
 b9c: 54000561  b.ne c48 <sub_b30+0x118>  // b.any
 ba0: f9400fe0  ldr x0, [sp, #24]
 ba4: 91001c00  add x0, x0, #0x7
 ba8: 39400001  ldrb w1, [x0]
 bac: f9400be0  ldr x0, [sp, #16]
 bb0: 91004400  add x0, x0, #0x11
 bb4: 39400000  ldrb w0, [x0]
 bb8: 6b00003f  cmp w1, w0  //key[7] = fixed_value1[0x11]
 bbc: 54000461  b.ne c48 <sub_b30+0x118>  // b.any
 bc0: f9400fe0  ldr x0, [sp, #24]
 bc4: 91000400  add x0, x0, #0x1
 bc8: 39400001  ldrb w1, [x0]
 bcc: f9400be0  ldr x0, [sp, #16]
 bd0: 91003800  add x0, x0, #0xe
 bd4: 39400000  ldrb w0, [x0]
 bd8: 6b00003f  cmp w1, w0  //key[1] = fixed_value1[0xe]
 bdc: 54000361  b.ne c48 <sub_b30+0x118>  // b.any
 be0: f9400fe0  ldr x0, [sp, #24]
 be4: 91001400  add x0, x0, #0x5  //key[5]
 be8: 39400001  ldrb w1, [x0]
 bec: f9400be0  ldr x0, [sp, #16]
 bf0: 9100d000  add x0, x0, #0x34  //fixed_value1[0x34]
 bf4: 39400000  ldrb w0, [x0]
 bf8: 6b00003f  cmp w1, w0  //key[5]=fixed_value1[0x34]
 bfc: 54000261  b.ne c48 <sub_b30+0x118>  // b.any
 c00: f9400fe0  ldr x0, [sp, #24]
 c04: 39400001  ldrb w1, [x0]
 c08: f9400be0  ldr x0, [sp, #16]
 c0c: 9100d400  add x0, x0, #0x35
 c10: 39400000  ldrb w0, [x0]
 c14: 6b00003f  cmp w1, w0  //key[0]=fixed_value1[0x35]
 c18: 54000181  b.ne c48 <sub_b30+0x118>  // b.any
 c1c: f9400fe0  ldr x0, [sp, #24]
 c20: 91000800  add x0, x0, #0x2
 c24: 39400001  ldrb w1, [x0]
 c28: f9400be0  ldr x0, [sp, #16]
 c2c: 91000800  add x0, x0, #0x2
 c30: 39400000  ldrb w0, [x0]
 c34: 6b00003f  cmp w1, w0  //key[2]=fixed_value1[0x2]
 c38: 54000081  b.ne c48 <sub_b30+0x118>  // b.any
 c3c: f9400fe0  ldr x0, [sp, #24]
 c40: 97ffffab  bl aec <sub_aec>
 c44: d503201f  nop
 c48: a8c27bfd  ldp x29, x30, [sp], #32
 c4c: d65f03c0  ret

 

8개의 key문자를 새로운 value1을 통해서 만들고, <sub_aec>로 분기한다.

 

더보기

0000000000000aec <sub_aec>:
 aec: a9bd7bfd  stp x29, x30, [sp, #-48]!
 af0: 910003fd  mov x29, sp
 af4: f9000fe0  str x0, [sp, #24]
 af8: f9400fe0  ldr x0, [sp, #24]
 afc: 97ffff29  bl 7a0 <strlen@plt>
 b00: 2a0003e3  mov w3, w0  // w3=w0
 b04: f9400fe2  ldr x2, [sp, #24] // x2=key
 b08: 528003e1  mov w1, #0x1f                   // #31
 b0c: 90000000  adrp x0, value2@page 
 b10: 91382000  add x0, x0, value2@pageoff // x0=value2
 b14: 97ffffba  bl 9fc <sub_9fc>
 b18: f90017e0  str x0, [sp, #40]
 b1c: f94017e0  ldr x0, [sp, #40]
 b20: 97ffff3c  bl 810 <puts@plt>
 b24: d503201f  nop
 b28: a8c37bfd  ldp x29, x30, [sp], #48
 b2c: d65f03c0  ret

 

<sub_aec>는 <sub_ab8>같이 <sub_9fc>를 실행시키기위한 준비 함수처럼 보면된다.

 

그 후, 또다시 <sub_9fc>가 실행되는데 로직은 같으니 설명은 생략한다.

 

이런식의 흐름을 파악한 뒤, 문제푸는 코드를 짤 수 있다.

 

value0 =[0x96, 0x19, 0x7, 0x11, 0x99, 0x19, 0x2, 0x11] 
value1 =[0xF7, 0x7B, 0x64, 0x75, 0xFC, 0x7F, 0x65, 0x79, 0xFF, 0x73, 0x6C, 0x7D, 0xF4, 0x77, 0x6D, 0x61, 0xE7, 0x6B, 0x74, 0x65, 0xEC, 0x6F, 0x75, 0x69, 0xEF, 0x63, 0x46, 0x53, 0xDA, 0x5D, 0x47, 0x57, 0xD1, 0x51, 0x4E, 0x5B, 0xD2, 0x55, 0x4F, 0x5F, 0xD9, 0x49, 0x56, 0x43, 0xCA, 0x4D, 0x57, 0x47, 0xC1, 0x41, 0x5E, 0x4B, 0xA9, 0x28, 0x30, 0x22, 0xA2, 0x2C, 0x31, 0x26, 0xA1, 0x20]
value2 = [0x69, 0x22, 0x22, 0x38, 0x1F, 0x43, 0x5B, 0x1C, 0x45, 0xE, 0x3C, 0x8, 0x5, 0x5E, 0x30, 0x17, 0x5F, 0x1B, 0x6, 0x19, 0x3B, 0x44, 0x7, 0x17, 0x6E, 0x7, 0x53, 0x1E, 0x17, 0x55, 0x12]




def sub_9fc(str1, str2 , num1, num2): 
    for i in range (num2):
        str2[i] = str2[i]^str1[i%num1]
        
    return str2

def decode(str1):
    flag = ''
    for i in str1:
        flag+=chr(i)
    return flag

fixed_value1 = sub_9fc(value0,value1,8,62)

key = [0 for i in range(8)]

key[6] = fixed_value1[0xe]
key[4] = fixed_value1[0x3]
key[3] = fixed_value1[0xa]
key[7] = fixed_value1[0x11]
key[1] = fixed_value1[0xe]
key[5] = fixed_value1[0x34]
key[0] = fixed_value1[0x35]
key[2] = fixed_value1[0x2]

_key=decode(key)
print(_key)

fixed_value2 = sub_9fc(key,value2,8,31)
flag = decode(fixed_value2)


print(flag)

1ockd0or

XMAS{s4nta_can_enter_the_h0use}

반응형