将附件拖入ida,根据字符串可判断为go语言编写的程序:
动态运行发现是编写的一个简易shell,并且需要一个Cert才能正常工作:
逆向golang程序时,ida反编译功能基本报废,最好的办法就是看汇编。golang中的函数调用约定和标准的函数调用约定有所区别:传参用到的寄存器依次是:AX,BX,CX,DI,SI,R8,R9,R10,R11。接下来开始逆向工作。
首先根据报错字符串"Cert Is A Must"定位到地址0x4C1FC0处的函数,此函数依次将报错字符串从rodata段取出放到.bss段中以供后续调用:
根据字符串"Cert Is A Must"的交叉引用可以找到解析输入的函数,地址为0x4C1900。该函数首先会判断全局变量qword_5D1128是否为0,如果为0就去比较[rax]是否为指向字符串"cert"的字符串指针,[rax+8]处是否为4,任意条件不满足就会触发"Cert Is A Must"的报错:
直接使用gdb进行动态调试,将断点打在此函数开头处,观察rax寄存器的值:
可以发现用户输入被空格分开了,并且使用指针+长度的结构进行储存,rax指向的就是这样一个结构的数组。对应的rbx是这个数组的长度。所以只要用户输入被空格分开后的第一部分为字符串"cert"即可绕过报错"Cert Is A Must":
紧接着的是报错"Missing parameter",继续分析汇编,如果用户输入的第一部分为"cert"即可来到loc_4C1A24:
这里会再次比较输入的第一部分的长度,如果长度大于3就执行右边的逻辑块,小于三九执行左边的逻辑块。"cert"长度为4,所以会进入右边,这时候程序会判断用户输入是"cert"还是"echo",如果为"cert",就会检查rbx的值是否为3,如果不是3就会触发报错"Missing parameter":
根据上文的分析,rbx就是输入被空格分割成的份数,所以输入格式应该为"cert xxx xxx"。继续分析汇编,如果rbx为3,程序就会去判断输入的第二部分长度是否为9,并且和字符串"nAcDsMicN"进行比对,如果不同就会触发报错"Internal Err0r":
相同会进入0x4C14A0处的cert的解析函数,并且将输入的第三部分和其长度作为参数:
解析函数首先会进行rc4处理,然后再进行base64处理再和字符串“JLIX8pbSvYZu/WaG”进行比较,如果相同就会输出成功提示,并将全局变量qword_5D1128赋值为1。动态调试即可提取出rc4的key,将字符串base64解码、异或rc4的key即可得出要输入的值。脚本如下:
得出输入第三部分为"S33UAga1n@#!",所以输入"cert nAcDsMicN S33UAga1n@#!"之后即可通过检查,将qword_5D1128赋值为1,再次进入0x4C1900处的函数是就会直接跳过cert的判断,之后即可正常进行交互:
简单分析汇编逻辑会发现只有ls、cat、whoami、cd、echo这几个命令,其中cd会调用chdir函数,ls会执行ls -al
命令,whoami和cat是调用的print打印写死的东西而echo的处理函数中存在溢出,在0x4C1854附近:
rax为索引,格式为echo part1 part2 part3 part4 ....
,每个part最多0x200,总共加起来最多0x400,echo处理函数会将各个part整合起来写在栈上,如果有“+”则跳过栈上对应的位置的数据。而rsp+0x68距离返回地址的距离只有0x200多,所以存在一个栈溢出漏洞,构造payload进行rop即可。
遇到golang逆向或者pwn直接放弃伪代码边看汇编边调试 -.-
from
pwn
import
*
my
=
b
'nihaonihaoni'
my_c
=
p64(
0xdfb5dbb8c64ce819
)
+
p32(
0xce2bd261
)
key
=
[
0
]
*
12
for
i
in
range
(
12
):
key[i]
=
my[i]^my_c[i]
final_base64
=
b
"JLIX8pbSvYZu/WaG"
final
=
b
'\x24\xb2\x17\xf2\x96\xd2\xbd\x86\x6e\xfd\x66\x86'
res
=
[
0
]
*
12
for
i
in
range
(
12
):
res[i]
=
final[i]^key[i]
print
(bytes(res))
from
pwn
import
*
my
=
b
'nihaonihaoni'
my_c
=
p64(
0xdfb5dbb8c64ce819
)
+
p32(
0xce2bd261
)
key
=
[
0
]
*
12
for
i
in
range
(
12
):
key[i]
=
my[i]^my_c[i]
final_base64
=
b
"JLIX8pbSvYZu/WaG"
final
=
b
'\x24\xb2\x17\xf2\x96\xd2\xbd\x86\x6e\xfd\x66\x86'
res
=
[
0
]
*
12
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: