WHCTF2017-ONLINE逆向題目BabyREwriteup
阿新 • • 發佈:2018-10-31
題目連結:http://oj.xctf.org.cn/media/task/2b0a8eaf-72ee-4893-bd4e-304f145cc970.babyRE
IDAx64載入 很容易找到關鍵就在main()
int __cdecl main(int argc, const char **argv, const char **envp) { char s; // [rsp+0h] [rbp-20h] int v5; // [rsp+18h] [rbp-8h] int i; // [rsp+1Ch] [rbp-4h] for ( i = 0; i <= 181; ++i ) { envp = (const char **)(*((unsigned __int8 *)judge + i) ^ 0xCu); *((_BYTE *)judge + i) ^= 0xCu; } printf("Please input flag:", argv, envp); __isoc99_scanf("%20s", &s); v5 = strlen(&s); if ( v5 == 14 && (unsigned int)judge(&s) ) puts("Right!"); else puts("Wrong!"); return 0; }
如果想走到Right就得滿足兩個條件 第一就是輸入的字串長度得等於14第二個就要分析judge函數了
judge endp ; sp-analysis failed
報錯堆疊不平衡
解決辦法看這裡https://blog.csdn.net/xiangshangbashaonian/article/details/81950110
void __usercall judge(__int64 [email protected]<rcx>, int [email protected] <r14d>)
{
bool v2; // zf
__int64 v3; // [rsp-8h] [rbp-8h]
v2 = (a2 & *(_DWORD *)(a1 - 44)) == 0;
JUMPOUT(v3, v3);
}
F5之後還是很模糊 main()中有對judge的操作 剛開始想不通是幹嘛(ps:太菜了)
IDA遠端動態除錯一下看看到底是怎麼回事
我是在for迴圈開始這裡下的斷點 其實感覺下在main入口更好點
分析可知:judge()函式剛開始是需要在main()中解密的 具體過程看下邊
.text:0000000000400615 jmp short loc_400637
.text:0000000000400617 ; ---------------------------------------------------------------------------
.text:0000000000400617
.text:0000000000400617 loc_400617: ; CODE XREF: main+38↓j
.text:0000000000400617 mov eax, [rbp+var_4]
.text:000000000040061A cdqe ; 使用eax的最高位拓展rax高32位的所有位
.text:000000000040061C movzx eax, byte ptr judge[rax] ; 取出judge位置的值賦給eax
.text:0000000000400623 xor eax, 0Ch ; 讓eax與0xC異或 並把結果放回eax
.text:0000000000400626 mov edx, eax ; 把eax得值賦給edx
.text:0000000000400628 mov eax, [rbp+var_4]
.text:000000000040062B cdqe
.text:000000000040062D mov byte ptr judge[rax], dl
.text:0000000000400633 add [rbp+var_4], 1 ; 這裡存放迴圈變數i 每次到這裡加1
.text:0000000000400637
.text:0000000000400637 loc_400637: ; CODE XREF: main+F↑j
.text:0000000000400637 cmp [rbp+var_4], 181 ; 比較i與181的大小
.text:000000000040063E jle short loc_400617 ; 若i<=181 則跳轉繼續迴圈 否則跳出
.text:0000000000400640 mov edi, offset format ; "Please input flag:"
[stack]:00007FFF8E6AB7FC db 2 ; 迴圈變數i在堆疊中的位置 第二次迴圈時值為2
那麼我們只需要寫個指令碼解密一下 就可以看到正常的judge()函式啦
在IDA中看初始位置0x600B00
IDC指令碼就可以
auto i;
for(i=0;i<0xb5;i++)
{
PatchByte(0x600b00+i,Byte(0x600b00+i) ^ 0xc);}
解密後關鍵程式碼就是 將序號與對應位置字元進行異或
那麼我們只要寫個指令碼異或一下就可以得到flag
a = [0x66,0x6D,0x63,0x64,0x7F,0x6B,0x37,0x64,0x3B,0x56,0x60,0x3B,0x6E,0x70]
flag = ''
for i in range(len(a)):
flag +=chr(a[i] ^ i)
print flag
print flag
#flag{n1c3_j0b}