1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[rev] decompile me (zer0pts CTF 2023) writeup

Last updated at Posted at 2024-12-19


バイナリファイルが与えられる。逆アセンブル結果はこれ。

void main(void)

{
  int iVar1;
  undefined4 extraout_var;
  long lVar2;
  undefined8 *puVar3;
  undefined8 local_208 [16];
  undefined local_188 [384];
  
  puVar3 = local_208;
  for (lVar2 = 0x200; lVar2 != 0; lVar2 = lVar2 + -1) {
    *(undefined *)puVar3 = 0;
    puVar3 = (undefined8 *)((long)puVar3 + 1);
  }
  local_208[0] = 0x80;
  write(1,"FLAG: ",0xe);
  read(0,local_208,0x80);
  RC4_setkey(&key,sbox);
  RC4_encrypt(local_208,local_188,sbox);
  iVar1 = memcmp(local_188,&enc,0x80);
  if (CONCAT44(extraout_var,iVar1) == 0) {
    puts("Correct!");
  }
  else {
    puts("Wrong...");
  }
  return;
}

ユーザー入力をRC4で暗号化し、encと照合して結果を返す。よってenckeyで復号化すればflagが得られそうに見えるが、そうはいかない。

処理を追っていく。memcmpが呼び出し規約の異なる独自実装となっていて、関数内部では引数__s1の代わりにR14を使用している。よく見ると__s2も引数ではなく変数datを参照している。

                             int  __stdcall  memcmp (void *  __s1 , void *  __s2 , size_t  _
             int               EAX:4          <RETURN>
             void *            RDI:8          __s1
             void *            RSI:8          __s2
             size_t            RDX:8          __n
                             memcmp                                          XREF[1]:     main:001012bd (c)   
        0010115b 31  c0           XOR        EAX ,EAX
        0010115d 31  c9           XOR        ECX ,ECX
        0010115f 48  8d  35       LEA        __s2 ,[dat ]                                      = 4c0733dc85c4cf78
                 1a  2e  00  00
                             lx                                              XREF[1]:     00101173 (j)   
        00101166 41  8a  1c  0e    MOV        BL,byte ptr [R14  + RCX *0x1 ]
        0010116a 32  1c  0e       XOR        BL,byte ptr [__s2  + RCX *0x1 ]=>dat               = 4c0733dc85c4cf78
        0010116d 08  d8           OR         AL,BL
        0010116f ff  c1           INC        ECX
        00101171 39  d1           CMP        ECX ,__n
        00101173 72  f1           JC         lx
        00101175 c3              RET

ではR14はどこから来たのか。RC4_setkeyRC4_encryptを見てみる。

                             undefined  RC4_setkey ()
             undefined         AL:1           <RETURN>
                             RC4_setkey                                      XREF[1]:     main:0010128d (c)   
        00101176 31  c9           XOR        ECX ,ECX
        00101178 31  d2           XOR        EDX ,EDX
                             .loop_init_sbox                                 XREF[1]:     00101187 (j)   
        0010117a 41  88  4c       MOV        byte ptr [R13  + RCX *0x1 ],CL
                 0d  00
        0010117f ff  c1           INC        ECX
        00101181 81  f9  00       CMP        ECX ,0x100
                 01  00  00
        00101187 72  f1           JC         .loop_init_sbox
        00101189 31  c9           XOR        ECX ,ECX
        0010118b 31  db           XOR        EBX ,EBX
                             .loop_key_schedule                              XREF[1]:     001011c4 (j)   
        0010118d 41  0f  b6       MOVZX      EAX ,byte ptr [R13  + RCX *0x1 ]
                 44  0d  00
        00101193 01  c2           ADD        EDX ,EAX
        00101195 41  0f  b6       MOVZX      EAX ,byte ptr [R12  + RBX *0x1 ]
                 04  1c
        0010119a 01  c2           ADD        EDX ,EAX
        0010119c 0f  b6  d2       MOVZX      EDX ,DL
        0010119f 41  8a  7c       MOV        DIL ,byte ptr [R13  + RDX *0x1 ]
                 15  00
        001011a4 41  8a  74       MOV        SIL ,byte ptr [R13  + RCX *0x1 ]
                 0d  00
        001011a9 41  88  74       MOV        byte ptr [R13  + RDX *0x1 ],SIL
                 15  00
        001011ae 41  88  7c       MOV        byte ptr [R13  + RCX *0x1 ],DIL
                 0d  00
        001011b3 ff  c3           INC        EBX
        001011b5 83  fb  08       CMP        EBX ,0x8
        001011b8 72  02           JC         .skip_mod_keylen
        001011ba 31  db           XOR        EBX ,EBX
                             .skip_mod_keylen                                XREF[1]:     001011b8 (j)   
        001011bc ff  c1           INC        ECX
        001011be 81  f9  00       CMP        ECX ,0x100
                 01  00  00
        001011c4 72  c7           JC         .loop_key_schedule
        001011c6 c3              RET
                             undefined  RC4_encrypt ()
             undefined         AL:1           <RETURN>
                             RC4_encrypt                                     XREF[1]:     main:001012a4 (c)   
        001011c7 31  c9           XOR        ECX ,ECX
        001011c9 31  d2           XOR        EDX ,EDX
        001011cb 31  db           XOR        EBX ,EBX
                             .loop_encrypt                                   XREF[1]:     00101218 (j)   
        001011cd ff  c2           INC        EDX
        001011cf 0f  b6  d2       MOVZX      EDX ,DL
        001011d2 41  0f  b6       MOVZX      EAX ,byte ptr [R13  + RDX *0x1 ]
                 44  15  00
        001011d8 01  c3           ADD        EBX ,EAX
        001011da 0f  b6  db       MOVZX      EBX ,BL
        001011dd 41  8a  7c       MOV        DIL ,byte ptr [R13  + RDX *0x1 ]
                 15  00
        001011e2 41  8a  74       MOV        SIL ,byte ptr [R13  + RBX *0x1 ]
                 1d  00
        001011e7 41  88  74       MOV        byte ptr [R13  + RDX *0x1 ],SIL
                 15  00
        001011ec 41  88  7c       MOV        byte ptr [R13  + RBX *0x1 ],DIL
                 1d  00
        001011f1 41  0f  b6       MOVZX      EAX ,byte ptr [R13  + RDX *0x1 ]
                 44  15  00
        001011f7 41  0f  b6       MOVZX      EDI ,byte ptr [R13  + RBX *0x1 ]
                 7c  1d  00
        001011fd 01  f8           ADD        EAX ,EDI
        00101202 41  0f  b6       MOVZX      EAX ,byte ptr [R13  + RAX *0x1 ]
                 44  05  00
        00101208 41  32  04  0f    XOR        AL,byte ptr [R15  + RCX *0x1 ]
        0010120c 41  88  04  0e    MOV        byte ptr [R14  + RCX *0x1 ],AL
        00101210 ff  c1           INC        ECX
        00101212 81  f9  80       CMP        ECX ,0x80
                 00  00  00
        00101218 72  b3           JC         .loop_encrypt
        0010121a c3              RET

これらの関数も呼び出し規約が異なる。おそらくR12が鍵、R13がS-Box、R14が暗号化後の値、R15がユーザー入力に対応している。

main関数を見ているとR12に変数valをセットしている処理があった。

        0010123b 4c  8d  25       LEA        R12 ,[val ]                                       = 1145141919810931
                 36  2d  00  00

よって鍵がval、暗号化後の比較対象がdatだと分かるので、これらをバイナリの中から探して復号する。

solverを書く。RC4は暗号化と復号化の処理が同じになる。

val = bytes([
    0x31, 0x09, 0x81, 0x19, 0x19, 0x14, 0x45, 0x11
])

dat = bytes([
    0x78, 0xcf, 0xc4, 0x85, 0xdc, 0x33, 0x07, 0x4c,
    0x93, 0x35, 0xfb, 0x7c, 0x10, 0x8e, 0xbe, 0x93,
    0x28, 0xe6, 0x2e, 0x75, 0xda, 0x5e, 0x85, 0xc5,
    0x91, 0x15, 0x75, 0x89, 0x48, 0x0e, 0x29, 0xa4,
    0xf9, 0xa6, 0x3a, 0x6e, 0x1f, 0x84, 0xf7, 0x42,
    0xb0, 0x93, 0x31, 0xf0, 0x68, 0xc0, 0x43, 0x38,
    0x07, 0x32, 0x09, 0x57, 0xda, 0x32, 0x44, 0xcf,
    0xcd, 0x8f, 0xe5, 0xbf, 0xe3, 0xd6, 0xbb, 0x59,
    0x9a, 0x6a, 0x84, 0x85, 0xd3, 0x22, 0xa9, 0x8e,
    0xb5, 0xea, 0xbd, 0x57, 0xde, 0xb1, 0x6c, 0x93,
    0xe4, 0x74, 0x70, 0xac, 0x1a, 0x03, 0xd9, 0x16,
    0x9f, 0xbc, 0x97, 0xfb, 0x85, 0xd9, 0xa6, 0x9e,
    0xd4, 0xd6, 0x02, 0x59, 0xd5, 0x28, 0xb3, 0x93,
    0x16, 0xb6, 0xc4, 0x78, 0xc4, 0xa2, 0x12, 0xd2,
    0xef, 0xb1, 0x54, 0x18, 0xfd, 0x76, 0x51, 0xa3,
    0x5e, 0x57, 0xb8, 0x58, 0x4b, 0x1e, 0xe2, 0x41
])

# RC4 encrypt by copilot :)
def rc4(key, data):
    S = list(range(256))
    j = 0
    out = bytearray()
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    i = j = 0
    for b in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        out.append(b ^ S[(S[i] + S[j]) % 256])
    return bytes(out)

flag = rc4(val, dat)
print(flag)

flagが得られた。
zer0pts{d0n'7_4lw4y5_7ru57_d3c0mp1l3r}

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?