当前位置:   article > 正文

[ctf.show.reverse] 36D杯 tiny_ctfshow 36d杯

ctfshow 36d杯

程序极小,也不能运行也不能用ida,还有个提示 echo $?

用010打开,发现0x20后是一段代码。用pwntools的反编译功能直接反编译

  1. a = open('tiny','rb').read()[0x20:]
  2. print(a)
  3. from pwn import *
  4. context.arch='i386'
  5. print(disasm(a))
  6. '''
  7. 0: 5b pop ebx
  8. 1: 5b pop ebx
  9. 2: 5b pop ebx
  10. 3: 31 c9 xor ecx, ecx
  11. 5: 51 push ecx
  12. 6: 41 inc ecx
  13. 7: 41 inc ecx
  14. 8: eb 04 jmp 0xe
  15. a: 20 00 ...
  16. c: 01 00 ...
  17. e: 58 pop eax
  18. f: 68 07 52 f4 8a push 0x8af45207
  19. 14: 68 63 9a 3f 09 push 0x93f9a63
  20. 19: 8b 7c 8b fc mov edi, DWORD PTR [ebx+ecx*4-0x4] ;传入的flag 后半个,前半个,循环右移3位后与栈顶两个异或后为0
  21. 1d: c1 cf 03 ror edi, 0x3 ;第一次为 0x5d99429 和 0x93f9a63
  22. 20: 68 29 94 d9 05 push 0x5d99429 ;第二次为 0x5d99429 和 0x8af45207
  23. 25: 5a pop edx
  24. 26: 5e pop esi
  25. 27: 31 fe xor esi, edi
  26. 29: 31 f2 xor edx, esi
  27. 2b: 09 d0 or eax, edx
  28. 2d: e2 ea loop 0x19
  29. 2f: 31 db xor ebx, ebx
  30. 31: 85 c0 test eax, eax
  31. 33: 0f 95 c3 setne bl
  32. 36: 31 c0 xor eax, eax
  33. 38: 40 inc eax
  34. 39: cd 80 int 0x80
  35. '''

应了这个比赛的名字:36D里边到底是啥,全靠猜。

开头有ELF但是是32还是64呢?反编译后全是eXX,而且从栈里取数据,应该是32位。

题目的hint是echo $? 在unix系统里表示返回值这里0x36开始将eax清0再加1然后返回,所以结果一定是1,这个提示也就没用了。所以第一个猜想:0x36,0x38没用应该删掉

然后回到开头先是弹了3个到ebx,然后会用到从[ebx+ecx*4-4]里读数据,这个ebx到底是啥,这是第二个猜想:指向输入的flag的指针。 一般逆向都是输入flag然后验证

有了这两个猜想就可以看程序了

先是压两个数到栈,然后进行循环ecx是循环计数器先设置为2,每次loop会减1到0退出

从ebx+X读入一个数字然后循环右移3位 存在edi

再压入一个数然后弹出两个到edx,esi

把edx,esi,edi作异或运算,然后or到eax,eax是返回值,前面猜的是确定flag是否正确的返回值,那么根据unix类的规则,返回值0表示正确,由于eax是或运算,所以它一开始是0,然后两次循环都应该是0,也就是说输入的值循环右移后存在edi的值与栈顶两个值的异或结果相同。

再来看栈的情况,第一次是0x8af45207,0x93f9a63,0x5d99429(循环里后压入的) 也就是后两个的异或与输入值右移3位后相同

0x93f9a63^0x5d99429 == flag[1]>>>3

第二次栈里只有0x8af45207,0x5d99429(循环里后压入的)

0x8af45207^0x5d99429 == flag[0]>>>3

由于python在数字没有固定长度,所以也就没有循环右移指令,只能手工处理

  1. a = (0x93f9a63^0x5d99429)
  2. a = (a<<3 | a>>29)& 0xffffffff
  3. print(bytes.fromhex(hex(a)[2:])[::-1])
  4. a = (0x8af45207^0x5d99429)
  5. a = (a<<3 | a>>29)& 0xffffffff
  6. print(bytes.fromhex(hex(a)[2:])[::-1])
  7. #flag{t1nyPr0g}

最后一个问题,36D杯为啥用flag{}包起来而不是36D{}呢?!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/807584
推荐阅读
相关标签
  

闽ICP备14008679号