WHCTF2017-ONLINE逆向题目BabyREwriteup

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiangshangbashaonian/article/details/83178904

题目链接: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 a1@<rcx>, int a2@<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

猜你喜欢

转载自blog.csdn.net/xiangshangbashaonian/article/details/83178904