西湖论剑初赛2023 - re复现
坐牢一天,Dual personality
一眼看出远跳转改了 CS 寄存器把程序变成了 64bit-mod
但是后面的加密逻辑静态看完全看不懂,后面又觉得 babyRE
能做,看出 base8
以后被一个 SHA-1
校验卡了一个小时,最后爆破少了后面的六位没爆出来,大失败属于是😓
babyRE
ida 打开发现 main
函数啥也没有,一看到 TlsCallback
函数就明白了应该是个回调函数 + 异常处理的题,交叉引用找到了三个注册函数
一个一个点进去,发现这三个函数里面有六个子函数,在每个函数开始的地方下断点,一路 F9,就能找到加密函数的执行顺序。
首先可以看出输入为 0 - 9
的数字。
然后是对 408104
进行一个取反,直接调过去就行。
然后 hook 了GetLastError
函数,注册了 base8
加密,没什么用。
然后来到了 base8
加密,表就是之前的 byte_408104
, 值得注意的是,这里在加密以后,是从第 16 位开始与密文进行比对的,比较长度为 96 位,前面16位是由 input
的前6位生成的,在这里没有进行比对。
再按一次 F9, 发现是一个 SHA-1 校验,没啥用,当时比赛的时候以为是可以解密的某种加密算法,或者可以用 crypto 来解的算法,最后看出来是 SHA-1 直接裂开。
最后一步是RC4加密,值得注意的是,rc4_key
的地址和 input
的地址是连在一起的,且由 init_rc4
的调用可知长度为 6 位
加密对象就是我们之前 base8 编码出来的结果。
我们直接对 rc4_key
进行爆破,然后对解密出来的结果进行验证即可
1 |
|
运行以后,把解密的结果在进行一次 base8解码
最后在末尾接上爆破出来的 cr4_key
即可得到 DASCTF{561516915572239428449843076691286116796614807391}
Dual personality
刚看这题的时候以为是一堆反调试和花指令的题,但是patch了半天除了发现 0,0,0,0
是花以外就没啥发现了,一动调就发现了不对劲
在经过了函数sub_401120
以后,下面的数据被改变了,显然这是一个 SMC ,但是 analyze 以后的代码很奇怪
这是一个远跳转, 远跳转有一个隐形的操作,他会将代码段寄存器CS设置为跳转到的这个段对应的段选择子,我们把 opcode bytes 打开
发现 ida 出现了反汇编错误,真实逻辑是跳到 33:4011D0
这个地址,33
是 CS 寄存器的段选择子,当 CS 为 0x23 时程序为 32bit - mode,当 CS 为 0x33 时 程序为 64bit - mode ,显然程序也是利用了这一点进行了反调试。
但是本题纯静态调试嗯看也是能做的,从远跳转地址 4011D0
开始把 0, 0, 0 ,0
给 nop 掉就可以正常 analyze 并创建函数得到源代码,虽然有点抽象但是能看,下面是加密顺序。
sub_4011D0
中有一个反调试, gs:60h 获得PEB结构,mov al, [rax+2]
后。al
的值就是BeingDebugged
的值, 具体可见 BeingDebugged反调试技巧
由上面的
sub_4011D0
的函数可知,此时dword_407058
的值变成了0x5DF966AE - 0x21524111
,如果触发了反调试的话dword_407058
的值就是0xDEADBEEF
也是一个反调试
__ROL4__
可以从网上找到源码
我们先按顺序把加密流程写出来
1 |
|
然后写出 exp :
1 |
|
运行得到 DASCTF{6cc1e44811647d38a15017e389b3f704}
Berkeley
比赛的时候SG👴配了一天环境,但是后来发现好像根本不需要配环境
先放一段简介作为了解:BPF简介 - 知乎 (zhihu.com)
先扔进ida
看到这个函数,点进去找一找,找到program_attach_uprobe函数,查了一下
bpf_program__attach_uprobe() 用于绑定 uprobe 和 uretprobe 追踪目标的信息。
是个注册ebpf的函数,再往下找就能找到下面这个函数
点进 unk_30060
一看,发现 ELF
标志,显然是在程序中内嵌了一个 ELF 文件然后通过 bpf 得以在 x86_64 指令集下运行,文件大小为 8472 。
我们用 idapython 把 ELF 文件给 dump 出来,也可以用 010 editor
1 | import idc |
得到的 ELF 文件用 ida 无法分析,需要用 ghidra 进行分析,同时还要用到 分析 bpf 文件的插件 or 这个插件和安装说明
这个文件中主要有两个函数
1 | undefined8 LBB0_1(longlong lParm1) |
1 | undefined8 LBB0_2(void) |
而在下发的附件中,我们还能找到一个虚假的 check
函数,里面有一个虚假的 cipher
,但是我们点进去发现真正的 key
和 cipher
和其是相邻的
我们把 ghidra 反编译出来难看的代码复写一下:
1 | void check(char* flag) |
由于是逐字比较,可以直接爆破,且爆破范围都是在 key
中。
1 |
|
运行得到 DASCTF{71c2ac98ac8d99a2e8a95111449a7393}
EasyVT
参考 VT技术入门 或者 看雪上的一篇博客 ,附件有主程序和一个驱动程序,主程序逻辑比较简单
通过内联汇编给出十个 vm 操作依次执行,一个跑了 4 轮,但是具体干了什么发现找不到,得逆驱动程序。
ida 打开驱动程序,在 DriverEntry
附近找一找,发现核心分发函数 sub_401C90
,根据宏恢复一下符号
按照主程序中的顺序,发现题目就是通过 VT 把程序拆成了 10 段,并且函数都是自写的加密,一个 tea
, 一个 rc4
,还有一些赋值和交换的操作,需要注意的是,每次 rc4
加密以后都会有一个 swap
操作,但是最后扔进加密函数里的顺序是原来的顺序,因此我们在 tea
解密以后,需要把每 8 位数据的前四位和后四位调换,然后再进行 rc4
解密,解密后再换回去即可,同时注意 rc4 解密的时候是分成长度为 8 的小段解密的,密钥流只用到前 8 位。
1 |
|
运行得到 DASCTF{81920c3758be43705ba154bb8f599846}