Skip to content

inBINcible

Challenge Link: Nope

Category: reverse

Writeup: inBINcible

Get the key. The flag is: “NcN_” + sha1sum(key)

inbincible

觀察

這支程式執行後直接輸出 Nope! ,沒有任何輸入

% ./inbincible                   
Nope!

起手式

這個執行檔是 32 位元的,且是 static link

% file inbincible
inbincible: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

發現 main.main 應該是 go 的執行檔

% objdump -M intel -d inbincible
inbincible:     檔案格式 elf32-i386


Disassembly of section .text:

08048c00 <main.main>:
 8048c00:       65 8b 0d 00 00 00 00    mov    ecx,DWORD PTR gs:0x0
 8048c07:       8b 89 f8 ff ff ff       mov    ecx,DWORD PTR [ecx-0x8]
 8048c0d:       8d 44 24 c0             lea    eax,[esp-0x40]
 8048c11:       3b 01                   cmp    eax,DWORD PTR [ecx]
 8048c13:       77 0b                   ja     8048c20 <main.main+0x20>
 8048c15:       31 ff                   xor    edi,edi
 8048c17:       31 c0                   xor    eax,eax
 ...

go 起手式

總共有兩個函式在 main package 中

% go tool objdump inbincible | grep 'TEXT main\.' 
TEXT main.main(SB) /home/n/ctf/ncn_quals_2014/rev400/main.go
TEXT main.func.001(SB) /home/n/ctf/ncn_quals_2014/rev400/main.go
TEXT main.init(SB) /home/n/ctf/ncn_quals_2014/rev400/main.go

分析 main

過程中發現有取出 os.Args,可能是藉由參數輸入

   0x8048ef1 <main.main+753>:   cmp    DWORD PTR ds:0x814e17c,0x1
   0x8048ef8 <main.main+760>:   jbe    0x804937d <main.main+1917>
=> 0x8048efe <main.main+766>:   mov    ebx,DWORD PTR ds:0x814e178
   0x8048f04 <main.main+772>:   add    ebx,0x8
   0x8048f07 <main.main+775>:   mov    esi,DWORD PTR [ebx+0x4]
gdb-peda$ x/10gx 0x814e178
0x814e178 <os.Args>:    0x0000000218300000      0x0000000000000002
0x814e188 <persistent>: 0xf7fc91a400000000      0x00000000f7ff9000
0x814e198 <reflect.dummy>:      0x0000000000000000      0x0000000000000000
0x814e1a8 <sync.allPools>:      0x000000000814e03c      0x0000000000000000
0x814e1b8 <syscall.envs>:       0x0000004e1830e000      0x000000000000004e

接著比較 esiebp ,此時的 ebp 是固定的 0x10 ,而 esi 是參數的長度

猜測參數長度應該要是 0x10

   0x8048f07 <main.main+775>:   mov    esi,DWORD PTR [ebx+0x4]
   0x8048f0a <main.main+778>:   mov    ebx,DWORD PTR [esp+0x6c]
   0x8048f0e <main.main+782>:   mov    ebp,DWORD PTR [ebx+0x4]
=> 0x8048f11 <main.main+785>:   cmp    esi,ebp
   0x8048f13 <main.main+787>:   je     0x8049048 <main.main+1096>
   0x8048f19 <main.main+793>:   xor    ecx,ecx
   0x8048f1b <main.main+795>:   mov    ebp,DWORD PTR [esp+0x88]

分析 func.001

在中間發現 reverse 題常見的 xor ,目標是 ecxebp

此時的 ecx0x12ebp 則是參數的第一個字x47 ( 'G' )

0x8049456 <main.func+150>:   xor    ecx,ebp

接著比較了 clal

此時的 cl 是 xor 的結果,al 是前面取出的值

0x804946a <main.func+170>:   cmp    cl,al

如果兩者一樣的話,會透過 go channel 送出 0x1 給 main

猜測可能是只要 16 個字經過 xor 以後都一樣就可以通過了

解法

因為 xor 可以直接使用一樣的 key 來找到原始字串,所以只要取出 xor key 以及最後的答案就可以了

xor key

實際查看該位置後發現 key 只有 5 bytes ,經過測試後發現這 5 bytes 會一直循環

也就是 0x12, 0x45, 0x33, 0x87, 0x65, 0x12, 0x45, 0x33, 0x87, 0x65, 0x12, 0x45, 0x33, 0x87, 0x65, 0x12

gdb-peda$ x/2gx 0x18300024-0x8
0x1830001c:     0x4533876500000000      0x0000000000000012

ans

gdb-peda$ x/2gx 0x18300040
0x18300040:     0x0306330bb6447555      0x3344b247716002e9

xor

將兩個字串經過 xor 以後就可以得到原字串 G0w1n!C0ngr4t5!!