unicorn教程三

题目给了下列的shellcode
\xe8\xff\xff\xff\xff\xc0\x5d\x6a\x05\x5b\x29\xdd\x83\xc5\x4e\x89\xe9\x6a\x02\x03\x0c\x24\x5b\x31\xd2\x66\xba\x12\x00\x8b\x39\xc1\xe7\x10\xc1\xef\x10\x81\xe9\xfe\xff\xff\xff\x8b\x45\x00\xc1\xe0\x10\xc1\xe8\x10\x89\xc3\x09\xfb\x21\xf8\xf7\xd0\x21\xd8\x66\x89\x45\x00\x83\xc5\x02\x4a\x85\xd2\x0f\x85\xcf\xff\xff\xff\xec\x37\x75\x5d\x7a\x05\x28\xed\x24\xed\x24\xed\x0b\x88\x7f\xeb\x50\x98\x38\xf9\x5c\x96\x2b\x96\x70\xfe\xc6\xff\xc6\xff\x9f\x32\x1f\x58\x1e\x00\xd3\x80
这个shellcode是被混淆了的
我们可以使用pwntools自带的disasm快速根据shellcode返汇编代码
在这里插入图片描述
可以看到是x86-32的,而且调用了系统调用
所以思路类似于上一题,执行这段代码,然后对系统调用打hook,把参数print出来,然后再跳过去。
调用号放在eax寄存器,参数的顺序是:ebx,ecx,edx,esi,edi。在hook函数中使用reg_read读这几个寄存器
可以Hook一个int 80h指令,它由cd 80表示
hook函数如下
在这里插入图片描述
完整代码在6.py,运行后如下所示
在这里插入图片描述
第四、第五个参数应该没用到,第一次调用时15号调用,第二次是1号调用。15号是chmod,1号是exit。
chmod的参数应该是文件名,权限等。exit的参数的话,就是4194392,即0x400058
就是想办法确定chmod操作了什么文件,4194392应该是一个指针。修改hook函数,添加如下代码
在这里插入图片描述
完整代码在7.py,运行如下
在这里插入图片描述
可以看到chmod第一个参数为/etc/shadow,第二个参数为438,即:
在这里插入图片描述
至此分析完毕
系统调用sys_chmod第一个参数为0x40058->/etc/shadow
第二个参数为0666
系统调用sys_exit第一个参数为0x400058

接下来看下一题,给出二进制文件
在这里插入图片描述
可以看到是32位的可执行程序
在这里插入图片描述
已知:
1.它被编译时的命令为gcc function.c -m32 -o function
2.该二进制程序的代码如下
int strcmp(char *a, char *b)
{
//get length
int len = 0;
char *ptr = a;
while(*ptr)
{
ptr++;
len++;
}

//comparestrings
for(int i=0; i<=len; i++)
{
    if (a[i]!=b[i])
        return 1;
}

return 0;

}

attribute((stdcall))
int super_function(int a, char *b)
{
if (a==5 && !strcmp(b, “batman”))
{
return 1;
}
return 0;
}

int main()
{
super_function(1, “spiderman”);
}
我们的任务是修改程序的逻辑,使得返回值是1。
从逻辑中我们知道,只有传入的a为5,指针b指向batman字符串时才会返回1
根据stdcall调用约定,当模拟过程开始时,栈应该如下图所示。我们看到在下图中,RET只是返回地址(可以为任意值)。
在这里插入图片描述
可以写出以下代码
mu.mem_write(BASE, read("./function"))
r_esp = STACK_ADDR + (STACK_SIZE/2)
ESP在函数调用时指向此地址
STRING_ADDR = 0x40000000
mu.mem_write(STRING_ADDR, “batman\x00”)
在指定地址处写入batman
mu.reg_write(UC_X86_REG_ESP, r_esp)
设置esp
mu.mem_write(r_esp+4, p32(5))
设置第一个参数,即5
mu.mem_write(r_esp+8, p32(STRING_ADDR))
设置第二个参数,即指向字符串batman的指针
然后要确定superfunction的起始和结束地址
IDA x86载入
在这里插入图片描述
直接看super function
在这里插入图片描述
在上图中可以看到起始地址为57B,结束地址为5B1,所以有
mu.emu_start(0x0000057B, 0x000005B1)
最后打印出eax寄存器来确认返回值是否为1
return_value = mu.reg_read(UC_X86_REG_EAX)
print “The returned value is: %d” % return_value
完整代码在8.py
运行后如图所示

在这里插入图片描述

来看最后一题
在这里插入图片描述
使用file查看
在这里插入图片描述
是ARM架构下32位可执行程序,要求我们得出给程序的计算结果,由于这是arm架构下的程序,所以直接运行会报错
在这里插入图片描述
只能通过unicorn模拟了
先IDAx86载入
在这里插入图片描述
使用F5查看main函数的反汇编
在这里插入图片描述
关注ccc起始和结束地址
起始地址:
在这里插入图片描述
结束地址
在这里插入图片描述
所以有:
CCC_START = 0x000104D0
CCC_END = 0x00010580
定义一个栈用于存储参数
stack = []
定义一个字典用于保存给定函数参数返回值
关键还是hook函数
在这里插入图片描述
显示判断是否在ccc函数起始处,如果是则读取第一个参数,这是由R0寄存器传入的
判断返回值是否已经存入字典,将返回值写入R0,将PC指向0x105bc,即BX LR指令,bx lr指令用于跳转到lr中存放的地址处,而lr的值为子程序返回的地址,在子程序返回时,把LR的值复制到程序计数器PC即可实现子程序返回。也就是说,此处设置PC指向0x105bc是为了实现子程序返回。
如果未为此参数保存返回值,请将其添加到堆栈。
在这里插入图片描述
当地址来到ccc结束处,即退出函数时我们已经知道参数了,然后读取保存在r0中的返回值
在这里插入图片描述
最后是得到main函数起始和结束地址
在这里插入图片描述
所以有
mu.emu_start(0x00010584, 0x000105A8)
最后通过读取r1得到计算结果
print “ret:{0}”.format(mu.reg_read(UC_ARM_REG_R1))
完整代码在9.py
运行后得到计算结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值