180208 逆向-Frida入门(2)

1625-5 王子昂 总结《2018年2月8日》 【连续第496天总结】
A. Frida入门
B.
参照一些例程学习了Frida的API

其实还是挺简单的

首先外部进行注入:
attach进程以后create_script创建发送给服务器的脚本,再load加载即可

def hook():
    session = frida.get_local_device().attach("CrackMe.exe")
    script = session.create_script(s)
    script.on('message', on_message)
    script.load()

通信

服务器和客户端通信有3种方式

  • 流,包括文件/标准输入输出stdin/stdout
  • console.log(),直接回显
  • send(message, [data,)

流输出

js内部进行操作,可以File文件对象来写入,也可以new NativeFunction调用函数/库携带的输出函数printf/puts等

console.log

很显然就是在客户端进行输出,跟标准输出流的效果一样

send()

这是一个异步的操作,有好处也有坏处
send(message, [data)调用以后会将信息交给服务器,由frida服务器发送给客户端
异步的好处就是它不会影响原程序执行的速度
坏处就是如果send过多,还没有发完原程序就结束了,那么服务器也会跟着结束,而无法发出剩下的msg

调用前需要将客户端绑定message信号和回调函数on_message,回调函数有message和data两个参
除了message信号以外还有一个destroyed信号,很显然是退出时调用的,回调函数无参

另外send函数调用时需要注意格式,message是JSON类型,data则是bytes类型

因此在快速的程序中尽量避免使用send,来保证消息传递的完整性

脚本代码

核心部分通过Interceptor.attach来Hook,指定地址使得服务器将该地址改到指定的函数上,其他需求可以通过API来满足
例如寄存器可以通过this.context对象读取,内存可以通过dump读取等等

编写CrackMe的POC时只要Hook解释器的开头部分即可获得Pintools指令计数的相同效果,但是这只Hook一条指令可快多了

由于进程结束的极快,因此使用send函数只能收到寥寥几条,但是流输出却完整记录,因此调用了内部的printf函数来输出
外部通过管道来接收输出

脚本如下
不过每次跑20轮以后都会报frida.dll内存读取错误,感觉应该是多进程导致服务器溢出,但是kill等等也并不能消除影响,之后看看API啥的能怎么整……

import sys
import frida
import string
import subprocess

s = """
var printf = new NativeFunction(ptr('0x401410'), 'int', ['pointer', 'int']);

var target = ptr('0x401054');
var addrexit = ptr('0x401370');
var format = Memory.allocUtf8String('%d\\n');

var count = 0;

Interceptor.attach(target, function(args){
count++;
});

Interceptor.attach(addrexit, function(args){
printf(format, count);
});
"""


def hook():
    session = frida.get_local_device().attach("CrackMe.exe")
    script = session.create_script(s)
    script.load()

    return session



CMD = "F:\ctf\Whale\CrackMe\CrackMe.exe"
def main():
    global count
    global f
    global stat
    flag = ""
    f = 1
    stat = 0
    while(f):
        l = 0
        for i in (string.digits + string.ascii_letters + string.punctuation):
            count = 0
            f = 0
            p = subprocess.Popen(CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
            session = hook()
            pin, pout = p.stdin, p.stdout
            pin.write((flag + i + '\n').encode())
            pin.flush()
            pout.readline()
            pout.readline()
            count = int(pout.readline().decode()[:2])
            pin.close()
            pout.close()
            p.kill()
            session.detach()
            print(flag + i + ":" + str(count))
            if(count-l>0 and l):
                flag += i
                print("find: ", flag)
                break
            l = count

main()

你可能感兴趣的:(各种工具,CTF)