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()