2020网鼎杯-第一场
re
vm
两种解法,angr一把梭, 自己手动逆
解法1(angr)
angr我觉得比较重要的有三个点
- 起始找寻位置
- 需要到达的路径
- 避免走的路径
起始找寻位置,我们可以选main, 也可以选特定验证函数, 但是需要注意的是, 数据的找寻
需要到达的路径为: success, flag这种成功的路径
避免走的路径便为失败路径
所以我们需要在ida找着三条路.
起初我选了vm_operate这个函数作为起始找寻位置,但是没有成功, 后面我选了main函数
需要到达的路径便为输出flag处
避免走的路径则是exit这种
最后执行即可
1 | #!/usr/bin/env python |
不用一会就拿到flag了
757515121f3d478
解法2(手逆)
table如下
1 | [0x0000000A, 0x00000004, 0x00000010, 0x00000008, 0x00000003, 0x00000005, 0x00000001, 0x00000004, 0x00000020, 0x00000008, 0x00000005, 0x00000003, 0x00000001, 0x00000003, 0x00000002, 0x00000008, 0x0000000B, 0x00000001, 0x0000000C, 0x00000008, 0x00000004, 0x00000004, 0x00000001, 0x00000005, 0x00000003, 0x00000008, 0x00000003, 0x00000021, 0x00000001, 0x0000000B, 0x00000008, 0x0000000B, 0x00000001, 0x00000004, 0x00000009, 0x00000008, 0x00000003, 0x00000020, 0x00000001, 0x00000002, 0x00000051, 0x00000008, 0x00000004, 0x00000024, 0x00000001, 0x0000000C, 0x00000008, 0x0000000B, 0x00000001, 0x00000005, 0x00000002, 0x00000008, 0x00000002, 0x00000025, 0x00000001, 0x00000002, 0x00000036, 0x00000008, 0x00000004, 0x00000041, 0x00000001, 0x00000002, 0x00000020, 0x00000008, 0x00000005, 0x00000001, 0x00000001, 0x00000005, 0x00000003, 0x00000008, 0x00000002, 0x00000025, 0x00000001, 0x00000004, 0x00000009, 0x00000008, 0x00000003, 0x00000020, 0x00000001, 0x00000002, 0x00000041, 0x00000008, 0x0000000C, 0x00000001, 0x00000007, 0x00000022, 0x00000007, 0x0000003F, 0x00000007, 0x00000034, 0x00000007, 0x00000032, 0x00000007, 0x00000072, 0x00000007, 0x00000033, 0x00000007, 0x00000018, 0x00000007, 0xFFFFFFA7, 0x00000007, 0x00000031, 0x00000007, 0xFFFFFFF1, 0x00000007, 0x00000028, 0x00000007, 0xFFFFFF84, 0x00000007, 0xFFFFFFC1, 0x00000007, 0x0000001E, 0x00000007, 0x0000007A, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000] |
根据虚拟机指令集可进行一步步进行翻译
10为输入, 所以一开头是输入, table[0]就是10
然后照着指令翻译成handler, 同时最后有个比较
从这里截取每次的结果, 注意,那个je不能让他进去,我输入的是错误的,所以当然会进je底下代码,这里改成jmp
1 | 0x22,0x3F,0x34,0x32,0x72,0x33,0x18,0xA7,0x31,0xF1,0x28,0x84,0xC1,0x1E,0x7A |
handler为> 0xC前的合体
1 | A 4 |
取出大体, 在进行细分, 进行一步步算最终结果, 这里可以动态调试, 我就用动态调试的,先打印出我的输入
flag{123456789}
在od里看eax什么时候变成这个的时候注意了,
最后就是下面的
1 | flag[0]^ 0x10 - 5 = 0x22 |
求出结果
最后加上flag{757515121f3d478}
joker
解法1(动态调试)
全程单步的一道题,
长度为0x18前面跟了我好久,两个假的,我在那逆算法,后面追到这里面才是对的
F7跟进,里面不能下断,
到这里发觉就是个异或, 然后跑完前0x13位flag到最后卡死了,那个地方,给了5个东西%tp&:
不知道是啥, 然后那里判断过不去的, 结合srand, 猜测是对这5个数做了操作,盲猜为xor 毕竟只有xor能让你猜了,爆破一下,最后一位为} `
1 | code = "hahahaha_do_you_find_me?" |
解法2(idc脚本修改,静态查看)
1 | start = 0x401500 |
修改后啦一大片按code, 强制转换为code, 后面有个JMPOUT, 按U取消函数定义, 就可以F5了
很明显, 最后一部分
这里就是5个字符,猜异或
解法3(动态dump内存)
等他smc解密完成后
这里可以脱掉后,打开ida
也可以拿到完美的表现
boom
原来用内存dump的, 那种方式好麻烦… 步骤都好复杂,请教了下虾哥, 他用frida dump dex
安装frida
1 | pip install frida |
下载frida-server
雷电模拟器选x86
开启模拟器,adb连接上
1 | adb devices |
开启frida-server后,运行app
1 | frida-ps -U |
查看是否有进程
下载frida-dex-dump
确认app 运行起来了, 并且apk放在跟main.py同目录下, 运行main.py, 这里会报错,先安装click
1 | pip install click |
在
1 | python main.py |
脱完壳有dex
jadx打开dex
pwn
boom1
打开ida查看,发觉有点乱, 代码数量庞大, 只能看字符串
看到这里,发觉他有个main函数, 猜测, 这应该是一个编译器, 猜测仅仅是不够的, 验证, 拿LEA IMM JMP JSP BZ BNZ,在github对应code里搜寻一番,找到了源码
编译c语言代码的, 既然有编译器了, 那我们不是可以为所欲为,
首先说明,这个傻逼编译器不支持挺多东西的
不支持的东西我测试出来如下
- 变量声明的同时赋值, 需要分步,也就是先声明,后使用
- 不允许有两个printf语句, 有的话会报not allow
- 不允许prinf在执行语句中间,只能在最后面
第一步,打印下变量地址
1 | int main() |
这个下断点可以利用
1 | b printf |
这样输出结果同时,我们还可以vmmap看下这块内存在哪
这里计算出固定偏移为0x523fd8,直接改__free_hook为one_gadget
1 | int main() |
boom2
逆向还没逆出来,待更
本文作者:NoOne
本文地址: https://noonegroup.xyz/posts/72106f6e/
版权声明:转载请注明出处!