1. 程式人生 > >WHCTF2017-ONLINE逆向題目BabyREwriteup

WHCTF2017-ONLINE逆向題目BabyREwriteup

題目連結: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}

 

參考連結https://blog.csdn.net/whklhhhh/article/details/78005589