rust
文件{:download="rust_baby.exe"}
程序比较复杂的时候,可以从输入输出流入手
“暂停定位法”——在程序请求输入的时候,按下IDA的“暂停”,然后输入字符并回车,程序就会自动定位到暂停的位置,然后往下翻堆栈就可以找到调用 gets
/ scanf
等的位置
调用函数(即call)的时候,会把call下一条汇编指令进行压栈,所以看栈就可以查看函数调用
![[image-20240521200639606.png]]
双击进去
![[image-20240521200703033.png]]
就是这里了
在下面 v11
处打上断点,F9运行,然后检索各个寄存器,肯定有一个是存放了我们输入数据的地址
![[image-20240521200832503.png]]
一个一个按蓝色箭头跳过去看,发现是R12存着数据
![[image-20240521200903279.png]]
选中数据按F2设置硬件断点,F9运行,断到ntdll里了,看看堆栈,是这个函数调用的
![[image-20240521201510531.png]]
同样的,在下面打断点,F9运行,看寄存器
调用了一个memcpy
RAX 0x0000019206B72700 一般是返回值,打上硬件断点之后,确实断到了
但是没加密,打断点的时候取消掉 Read
,不行
继续调,跳出函数,检查寄存器,发现有奇奇怪怪的字符串
![[image-20240521203701150.png]]
![[image-20240521203709711.png]]
在函数里翻翻,发现一个奇怪的base64
![[image-20240521203738376.png]]
把 src\\main.rs
去掉,b64解密
![[image-20240521203553870.png]]
cryforhelp
解密之后是一串乱码
继续跟着硬件断点
![[image-20240521205718008.png]]
异或加密,长度是 13 * 8 = 104
,如果长度不够就填充 E
再异或
![[image-20240521210002150.png]]
但是并不只有异或,还有一个函数进行了加密
取 8 个字符 -> 转换成 long -> 加密 -> 异或 -> 存储
![[image-20240521211100039.png]]
这里猜是一个取模操作,因为下面有个v24++,经验证,确实是取模
这里需要根据结果反推算法
深入 sub_7FF6D去看,先看返回值是怎么来的
![[image-20240522154257435.png]]
在Hex View区域 G
一下 rsp
,然后盯着区域的数据变化,发现先赋值,然后又清零,又赋值,又清零,纯粹是用来哈人的
然后这里的加密就是加加减减
flag = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
r = []
for i in range(0, len(flag), 8):
tmp = -1
for sub_i in range(8):
r += [(flag[i + sub_i] + tmp) ^ 0x33]
if sub_i % 2 != 0:
tmp += 1
print(bytes(r))
加密完之后地址放在了 rbx
![[image-20240522154749298.png]]
在 rbx的地址下硬件断点
![[image-20240522154930604.png]]
断到这里了,这里 v93 是 r11,数组是 0,v96 是 rcx 是异或表,v91 是 r10 是刚加密后的数据
这个异或表多次测试,都是不变的,所以把加密后的字符串提取出来,全部异或 a 就可以拿到异或表
打硬件断点
![[image-20240522162357618.png]]
这里有一个复制内存,把刚异或之后的数据存到 v101
在 v101 下硬件断点
![[image-20240522162620376.png]]
是个base64加密,在加密后地方打硬件断点,就是比较了
- 代码较短,单步调试
- 不要被麻烦的东西吓到
- 输入流暂停定位
- 善用断点