逆向手在夹缝中艰难求生系列。
这篇真的存粹是做题笔记了,对内核驱动啥的不太懂,pwn也不会,能做出来的题都是硬逆出来的(
childre最后死活没整出来,后来看大佬的wp才知道对子进程有修改(。)呜呜呜多进程真的不太会啊。
REVERSE
obfu
一堆密码堆起来的题(密码菜鸡卑微落泪
按逻辑来说拿到serial number就能拿到flag了。
通过findcrypt找到三个加密算法的常量,通过交叉引用确定函数用途。
v10和v8相比之下v8更容易出,v8跟输入没有关系,相当于已知字符串(=md5(“admin”)。
然后就是enctrpy函数。
按照顺序是AES_enc->RC4_dec->循环左移三位复原。
exp:
1 | from binascii import * |
拿到serial:653b987431e5a2fc7c3d748fba008869
最后拿到flag:0725f66471f85ba9d742eb583c75959c
decryption
送!分!题!泪目了呜呜呜呜呜
加密函数在这里:
懒得逆逻辑了,直接copy算法爆破(毕竟是按字节加密hhh。
1 | arr=[0x12, 0x45, 0x10, 0x47, 0x19, 0x49, 0x49, 0x49, 0x1A, 0x4F, 0x1C, 0x1E, 0x52, 0x66, 0x1D, 0x52, 0x66, 0x67, 0x68, 0x67, 0x65, 0x6F, 0x5F, 0x59, 0x58, 0x5E, 0x6D, 0x70, 0xA1, 0x6E, 0x70, 0xA3] |
flag:1e1a6edc1c52e80b539127fccd48f05a
babyre
乍一看主函数逻辑很简单,实际上如果不patch的话是不可能完成的(byte_41A808这里有不可见字符。
看到这篇wp(HWS计划2021硬件安全冬令营线上选拔赛 re wp_20000s的博客-CSDN博客)里说是“内部加载dll,hook了驱动”,好像是这样,不过为啥动态调试的时候没有hook到呢(tcl不懂,选择手动hook
然后注意到了2047这个奇怪的数字,正常来说ZwLoadDriver应该是不会返回这种东西的(吧,所以从左边函数表一个一个翻下来找到了关键函数sub_412A20()
结合前面v9的赋值可以猜测,应该调用这个函数,并且a2是v9,才能对输入的Str调用v4进行加密得到byte_41A808。
所以先直接暴力patch
然后下断点,动态调试,可以看到v4实际上是:
噢,感谢密钥的提示,不用看了hhh,直接sm4解密(从SM4 python_dumpling-cat的博客-CSDN博客抓了脚本改了改)。
1 | # S盒 |
flag:42b061b4cb41cfa89ca78047bde1856e
Enigma
逻辑很清晰,直接分析loc_4018F0。
这边有一个SetUnhandledExceptionFilter捕获异常。
一开始以为下面的都是花指令,但每次都是0xC7转不了就很奇怪,异常+0xC7想到了平时用的CC断点,再加上sub_401630看起来像是个虚拟机,感觉0xC7是一个中断号(计组刚学,捕获中断然后用sub_401630处理。
每一个case里sub_4011B0是取值,另一个函数则是处理,v18是指令长度。
通过对ExceptionInfo的查阅发现,v19=*(_DWORD *)(*(_DWORD *)(a1 + 4) + 0xB8)
开始是异常发生的地址即0xC7的地址,最后则应该是异常处理完毕后要返回的用户空间代码地址。(这么一推异常应该是C7FF才对
opcode是C7FF的下一个即v19+2,后面的为操作数。
二级函数里面都是对a1[40]~a1[44]进行操作,猜测是寄存器。
于是可以分析出:
1 | // xx为[1,5],rx为对应的a1[40]~a1[44]寄存器,是二级函数中的case |
然后把下面的机器码中带有C7 FF系列指令以外的先转换成code。
接下来处理这些异常部分的机器码,比如第一个中断翻译出来是and r1,0
,即将r1清空,汇编习惯上更常用xor r1,r1
,先用注释标注。
然后根据上下文以及上图可以推断出r1-r5分别对应如下:
1 | r1 -> eax; |
patch程序,多余字节直接nop(因为不记得有些机器码了所以直接用keypatch。
然后得到反编译的加密函数。
根据逻辑逆向写出exp:
1 | from hashlib import md5 |
flag:751542a09b8b341dda23ebfc387a5e91
内核安全
easy_kernel
是个ring3调用ring0的题(前半部分。
从ring3看起,v7是flag,走了sub_401005函数。
跳到最后有
int 2E,查了一下是用户模式进入内核模式的中断,于是去看ring0(即DriverXP.sys,调用号是186。
可以看到这里有186,并且参数个数也是6个,猜测sub_401340就是调用的函数。
进一步可以看到,a1==-1,刚好也吻合sub_401005的第一个参数。
findcrypt可以看到DES,并且查交叉引用和反编译代码证实sub_401680就是DES加密过程。
可以看到这边密钥只用了”}aglf_T_ton_5i_sihT_yrroS{galf”的前八字节。
第一层加密确认,从ring3继续往下看。
这个MEMORY[0x5804E8]实在是没看出来是什么,看汇编是call fword ptr,查了一下是个长调用,返回用retf。
gdt表也懒得查,于是在ring3的汇编这里从头开始一个一个往下看retf,准备把碰到的都试一遍。
诶,看到一个,转函数看看。
代到exp里试了一下,发现成了,运气很好hhh,最开始这个就是MEMORY[0x5804E8]。
exp:
1 | from Crypto.Cipher import DES |
flag:c1878dfb2b0c23c74ec4e6650d8f7004
固件安全
NodeMCU
strings nodemcu.bin > str.out
,导出字符串后直接查找flag即可
flag:6808dcf0-526e-11eb-92de-acde48001122
STM
用bin2hex将bin文件转为hex文件,然后用ida加载hex。
查找STM的datasheet(以常见的STM32F103CB为参照)可知flash映射在0x08000000地址上
于是载入ida的时候还要把基址改成0x08000000。
然后查找字符串,直接看Hello World的交叉引用,找到主函数。
根据相应的函数功能猜测并命名,sub_8000314是加密函数。
逻辑很简单,直接写exp:
1 | arr=[0x7D, 0x77, 0x40, 0x7A, 0x66, 0x30, 0x2A, 0x2F, 0x28, 0x40, 0x7E, 0x30, 0x33, 0x34, 0x2C, 0x2E, 0x2B, 0x28, 0x34, 0x30, 0x30, 0x7C, 0x41, 0x34, 0x28, 0x33, 0x7E, 0x30, 0x34, 0x33, 0x33, 0x30, 0x7E, 0x2F, 0x31, 0x2A, 0x41, 0x7F, 0x2F, 0x28, 0x2E, 0x64] |
flag{1749ac10-5389-11eb-90c1-001c427bd493}