文章参考CTF-wiki
一路上踩了不少坑记录一下。

例题 NDH2K13-crackme-500

尝试用IDA打开发现section header 损坏,一路确认进去也没找到主函数,使用pintools对其进行分析。
输入命令

playmaker@playmaker-PC:~$  ~/pin-3.7-97619-g0d0c92f4f-gcc-linux/pin -t ./pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./Desktop/crackme <<< "a";cat inscount.out
Jonathan Salwan loves you <3
----------------------------

Password: Bad password
Count 162712
playmaker@playmaker-PC:~$  ~/pin-3.7-97619-g0d0c92f4f-gcc-linux/pin -t ./pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./Desktop/crackme <<< "aa";cat inscount.out
Jonathan Salwan loves you <3
----------------------------

Password: Bad password
Count 165508
playmaker@playmaker-PC:~$  ~/pin-3.7-97619-g0d0c92f4f-gcc-linux/pin -t ./pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./Desktop/crackme <<< "aaa";cat inscount.out
Jonathan Salwan loves you <3
----------------------------

Password: Bad password
Count 168304
playmaker@playmaker-PC:~$  ~/pin-3.7-97619-g0d0c92f4f-gcc-linux/pin -t ./pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./Desktop/crackme <<< "aaaa";cat inscount.out
Jonathan Salwan loves you <3
----------------------------

Password: Bad password
Count 171100

四次长度不同的数据,且执行指令数字逐渐增加,写一个脚本查看逐渐变长的规律

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from subprocess import Popen, PIPE
from sys import argv
import string
import time

pinPath = "/home/playmaker/pin-3.7-97619-g0d0c92f4f-gcc-linux/pin"
pinInit = lambda tool, elf: Popen([pinPath, '-t', tool, '--', elf], stdin = PIPE, stdout = PIPE)
pinWrite = lambda cont: pin.stdin.write(cont)
def pinRead():
	f = open('./inscount.out','r')
	file  = f.read().strip('\n')
	f.close()
	return file

if __name__ == "__main__":
    last = 0
    for i in xrange(1, 30):
        pin = pinInit("./pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so", "./Desktop/crackme")
        pinWrite("a" * i + '\n')
        time.sleep(0.5)
        now = int(pinRead().split("Count ")[1])
        
        print "inputLen({:2d}) -> ins({}) -> delta({})".format(i, now, now - last)
        last = now

运行结果如下

playmaker@playmaker-PC:~$ python guesslength.py
inputLen( 1) -> ins(159810) -> delta(159810)
inputLen( 2) -> ins(162606) -> delta(2796)
inputLen( 3) -> ins(165402) -> delta(2796)
inputLen( 4) -> ins(168198) -> delta(2796)
inputLen( 5) -> ins(170994) -> delta(2796)
inputLen( 6) -> ins(173790) -> delta(2796)
inputLen( 7) -> ins(176586) -> delta(2796)
inputLen( 8) -> ins(182307) -> delta(5721)
inputLen( 9) -> ins(182179) -> delta(-128)
inputLen(10) -> ins(184975) -> delta(2796)
inputLen(11) -> ins(187771) -> delta(2796)
inputLen(12) -> ins(190567) -> delta(2796)
inputLen(13) -> ins(193363) -> delta(2796)
inputLen(14) -> ins(196159) -> delta(2796)
inputLen(15) -> ins(198955) -> delta(2796)
inputLen(16) -> ins(201751) -> delta(2796)
inputLen(17) -> ins(204547) -> delta(2796)
inputLen(18) -> ins(207343) -> delta(2796)
inputLen(19) -> ins(210139) -> delta(2796)
inputLen(20) -> ins(212935) -> delta(2796)
inputLen(21) -> ins(215731) -> delta(2796)
inputLen(22) -> ins(218527) -> delta(2796)
inputLen(23) -> ins(221323) -> delta(2796)
inputLen(24) -> ins(224119) -> delta(2796)
inputLen(25) -> ins(226915) -> delta(2796)
inputLen(26) -> ins(229711) -> delta(2796)
inputLen(27) -> ins(243691) -> delta(13980)
inputLen(28) -> ins(243691) -> delta(0)
inputLen(29) -> ins(243691) -> delta(0)

长度位8时出现指令出现了激增,即可猜测flag的长度为8,接着可以猜测输入的正确的越多,执行的指令越多,于是写个逐位爆破脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from subprocess import Popen, PIPE
from sys import argv
import string
import pdb
import time

pinPath = "/home/playmaker/pin-3.7-97619-g0d0c92f4f-gcc-linux/pin"
pinInit = lambda tool, elf: Popen([pinPath, '-t', tool, '--', elf], stdin = PIPE, stdout = PIPE)
pinWrite = lambda cont: pin.stdin.write(cont)

def pinRead():
    #f = open('./inscount.out','r')
    f = open('./inscount.out','r')
    file  = f.read().strip('\n')
    f.close()
    return file

if __name__ == "__main__":
    last = 0
    
    dic = string.ascii_letters + string.digits + "+_ "
    pwd = '?' * 8
    dicIdx = 0
    pwdIdx = 0

    while True:
        pwd = pwd[: pwdIdx] + dic[dicIdx] + pwd[pwdIdx + 1: ]
    
        pin = pinInit("./pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/ManualExamples/obj-intel64/inscount0.so","./Desktop/crackme")
        pinWrite(pwd + '\n')
        time.sleep(1)

        now = int(pinRead().split("Count ")[1])

        print "input({}) -> now({}) -> delta({})".format(pwd, now, now - last)

        if now - last > 2000 and dicIdx:
            pwdIdx += 1
            dicIdx = -1
            last = 0
            if pwdIdx >= len(pwd):
                print "Found pwd: {}".format(pwd)
                break

        dicIdx += 1
        last = now

得到flag
在这里插入图片描述

PinCTF

还有一个简便工具,但是上题的题目PinCTF解决不了
下载地址以及使用教程
注:下载解压好运行./install.sh,并且pip安装好相关库即可用

Logo

更多推荐