Pin-in-ctf 学习分析

前言

这次打qctf,做到了一个ollvm,控制流平坦化的题,虽然不是很明白原理(但这么叫感觉很6批)。听师傅们说可以用pin解决,于是先学习一下pin在ctf中的应用,为解决olvm铺路。

应用

具体的pin和pintool我就不说了

0x0

NDH2k13-crackme-500
首先看到这个文件700+k,一看就不好分析,nm提示内存分配太多?,IDA打开,提示各种错误,不多我还是强行将其打开了。搜索字符串,无果。此题可能得靠天!
好了,是时候拿出利器pin了。
这里尝试用最简单的pintool,inscount0.so,使用方法如下:
make obj-intel64/inscount0.so TARGET=intel64 编译生成64位的pintool
make obj-ia32/inscount0.so 编译生成32位的pintool
pin -t your_pintool -- your_binary <arg>使用基本命令
我修改了inscount0.cpp使其能在执行完成后,将输出到终端上。
这里写图片描述
对于指令数来说,最简单的猜想就是会不会和输入的长度以及输入的字符有关,首先尝试输入不同长度的字符串。确实是存在规律的。
代码如下:

import subprocess
import os
import logging
import json
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# js = json.dumps(ssst, sort_keys=True, indent=4, separators=(',', ':'))# format json output


class shell(object):
    def runCmd(self, cmd):
        res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        sout, serr = res.communicate()
        return res.returncode, sout, serr, res.pid

    def initPin(self, cmd):
        res = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        self.res = res

    def pinWrite(self, input):
        self.res.stdin.write(input)

    def pinRun(self):
        sout, serr = self.res.communicate()
        return sout, serr


filename = "/home/jeb/Documents/pin-in-CTF/examples/NDH2k13-crackme-500/crackme"
cmd = "/opt/pin-3.7-97619-g0d0c92f4f-gcc-linux/pin -t " + \
    "/opt/pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so" + " -- " + filename
# print shell.runCmd(cmd)
cout_old = 0
# for i in range(30):
#     res  = subprocess.Popen(cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
#     res.stdin.write("a"*i+'\n')
#     sout,serr = res.communicate()
#     cout = sout.split("Count ")[1]
#     cout_sub= int(cout) - cout_old
#     cout_old = int(cout)
#     print ("current len ", i,"current count:",cout,"sub_count ",cout_sub)
shell = shell()
shell.initPin(cmd)
cout_old=0
for i in range(30):
    shell.initPin(cmd)
    shell.pinWrite("a"*i)
    sout,serr = shell.pinRun()
    cout = sout.split("Count ")[1]
    cout_sub= int(cout) - cout_old
    cout_old = int(cout)
    print ("current len ", i,"current count:",cout,"sub_count ",cout_sub)

发现在len为8时,指令数出现了跃变,因此判断flag的长度为8位。继续探究。
知道了长度之后,尝试使用不同的字符,首先遍历第一个字符,发现在输入A时指令数量会出现突变,所以根据这点进行逐字节爆破。
代码如下:

cur=''
for i in range(8):
    for s in dic:
        shell.initPin(cmd)
        pwd = cur+s+'?'*(7-len(cur))
        print 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值