0.Frida基础入门(Windows-实现对exe程序插桩)

环境安装,感觉python比较好用就下载python版的!

# 安装 frida库  
pip install frida  
  
# 安装frida-tools工具  
pip install frida-tools

成功!

D:\CTF_Study\Reverse\Frida_Study>frida --version
16.1.11

先编写一个程序用来测试!
test.cpp,每输对一个字符i就会加一!

#include<iostream>
#include<stdlib.h>
#include<windows.h>
using namespace std;
typedef int status;
typedef int selemtype;
char flag[] = "flag{12321213}";
char w[] = "Wrong!";
char r[] = "Right!";

int main ()
{
        char input[256] = {0};
        gets(input);
        for(int i = 0 ; flag[i] ; i ++ ){
                if(flag[i]!=input[i]){
                        puts("Wrong!");
                        return 0;
                }
        }
        puts("Right!");
}

编译一下:

D:\CTF_Study\Reverse\Frida_Study> g++  .\test.cpp  -o test1.exe 

接下来就是拖入ida查看地址看看我们需要的地址了!

int __fastcall main(int argc, const char **argv, const char **envp)
{
  __int64 v4; // [rsp+20h] [rbp-60h] BYREF
  char v5[260]; // [rsp+28h] [rbp-58h] BYREF
  int i; // [rsp+12Ch] [rbp+ACh]

  _main(argc, argv, envp);
  v4 = 0i64;
  memset(v5, 0, 0xF8ui64);
  gets(&v4, v5);
  for ( i = 0; flag[i]; ++i )                   // ++i,序号增加的位置
  {
    if ( flag[i] != v5[i - 8] )
    {
      puts("Wrong!");                           // 插桩结束的位置
      Sleep(0x10u);
      return 0;
    }
  }
  puts("Right!");
  return 0;
}

看汇编:

.text:000000014000159E                 lea     rax, Buffer     ; "Wrong!"
.text:00000001400015A5                 mov     rcx, rax        ; Buffer
.text:00000001400015A8                 call    puts            ; 程序结束的地址
...
.text:00000001400015C2 ; ---------------------------------------------------------------
.text:00000001400015C2
.text:00000001400015C2 loc_1400015C2:                          ; CODE XREF: main+6C↑j
.text:00000001400015C2                 add     [rbp+0C0h+var_14], 1 ; 序号增加的位置
.text:00000001400015C9

得到偏移地址:0x15A8程序结束;0x15C2序号增加!

知道后就可以开始编写js代码了

var number = 0   //定义插桩数
function main()
{
    var base =  Module.findBaseAddress("test1.exe")//在电脑进程种查找程序
        
    if(base){    //成功找到
        Interceptor.attach(base.add(0x15A8), { //监听结束地址
        onEnter: function(args) {
	            send(number);  //输出数据
            }
        });
        
        Interceptor.attach(base.add(0x15C2), {//监听目标地址
            onEnter: function(args) {
                number+=1;
            }
        });
        Interceptor.attach(base.add(0x15EA), {//监听成功地址
            onEnter: function(args) {
                send("成功!");
            }
        });
    }
}
setImmediate(main);//设定插桩

下面就可以开始了!先双击启动程序test1.exe在来启动frida

D:\CTF_Study\Reverse\Frida_Study>frida -l .\hook.js -n test1.exe

成功启动:
请添加图片描述

尝试在test1.exe程序种输入不同的数据:
输入:aaaaaaa
结果:发现输出{‘type’: ‘send’, ‘payload’: 0}说明number为0

D:\CTF_Study\Reverse\Frida_Study>frida -l .\hook.js -n test1.exe
     ____
    / _  |   Frida 16.1.11 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Local System (id=local)

[Local::test1.exe ]-> message: {'type': 'send', 'payload': 0} data: None
Process terminated
[Local::test1.exe ]->

Thank you for using Frida!

输入:flag{adasda}
结果:发现输出{‘type’: ‘send’, ‘payload’: 5}说明number为5,正好对了5个字符

D:\CTF_Study\Reverse\Frida_Study>frida -l .\hook.js -n test1.exe
     ____
    / _  |   Frida 16.1.11 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Local System (id=local)

[Local::test1.exe ]-> message: {'type': 'send', 'payload': 5} data: None
Process terminated
[Local::test1.exe ]->

Thank you for using Frida!

输入:flag{12321213}
结果:发现输出{‘type’: ‘send’, ‘payload’: ‘成功!’}说明flag成功!

D:\CTF_Study\Reverse\Frida_Study>frida -l .\hook.js -n test1.exe
     ____
    / _  |   Frida 16.1.11 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Local System (id=local)

[Local::test1.exe ]-> message: {'type': 'send', 'payload': '成功!'} data: None
Process terminated
[Local::test1.exe ]->

Thank you for using Frida!

经过上面的测试我们就已经明白了如何使用frida的运用了!

那么接下来就是写脚本来爆破程序的flag了!
又发现一个问题:使用之前的js脚本有一个问题,就是js将数据发过来python还没接收到程序就结束了QAQ
所以先修改一下js脚本,直接hook掉puts函数添加一个延时几毫秒的函数就可以了:

var number = 0

function main()
{
    var base =  Module.findBaseAddress("test1.exe")
        
    if(base){
        Interceptor.attach(base.add(0x15C2), {//序号加1的位置
            onEnter: function(args) {
                number+=1;
            }
        });
        Interceptor.attach(base.add(0x15A8), {//程序报错的地址
            onEnter: function(args) {
                send(number);
            }
        });
        Interceptor.attach(base.add(0x15DC), {//成功的位置
            onEnter: function(args) {
                send(number);
            }
        });
        Interceptor.attach(base.add(0x2900), {//不让程序退出的太快!!直接hook掉puts函数
            onEnter: function (args) {
                // 延迟 10 秒钟
                var delay = 0x10;
                console.log("Program is ending, delaying for " + (delay / 1000) + " seconds...");
                var start = new Date().getTime();
                while (new Date().getTime() < start + delay);
                console.log("Delay complete.");
            }
        });

    }
}
setImmediate(main);

python脚本用来测试:

import subprocess
import frida
import time

def on_message(message, data):
    print(message)

filename = "test1.exe"
jscode = open("hook.js", "rb").read().decode()

process = subprocess.Popen(filename, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
session = frida.attach(filename)
script = session.create_script(jscode)
script.on('message', on_message)
script.load()
process.stdin.write("flag{12321213}")
output, error = process.communicate()
print(output)

输出:

PS D:\CTF_Study\Reverse\Frida_Study> & E:/python_env/python.exe d:/CTF_Study/Reverse/Frida_Study/exp.py
{'type': 'send', 'payload': 15}
Program is ending, delaying for 0.016 seconds...
Right!

成功解决程序退出过快的问题后就可以开始写爆破脚本了!

import subprocess
import frida
import time

flaglen = 14
flag = bytearray(b'!' * flaglen)
filename = "test1.exe"
jscode = open("hook.js", "rb").read().decode()


result = 0
def brute(F):

    def on_message(message, data):
        global result
        if message['type'] == 'send':
            result = message['payload']
        else:
            print(message)
    process = subprocess.Popen(filename, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               universal_newlines=True)

    session = frida.attach(filename)
    script = session.create_script(jscode)
    script.on('message', on_message)
    script.load()
    process.stdin.write(F.decode())

    output, error = process.communicate()
    process.terminate()
    return result

count = 0
new_number = brute(flag)
number = new_number
t = time.time()
st = t

while count < flaglen:
    number = brute(flag)
    if number > new_number:
        print(f"本位耗时:{time.time()-t}s,正确字符为:{chr(flag[count])}")
        t = time.time()
        print(flag.decode())
        new_number = number
        count += 1
    else:
        flag[count] += 1
        while(flag[count] > 127):
            flag[count] = 33
            count -= 1
            flag[count] += 1
print("最终flag!",flag.decode())
print(f"总耗时{time.time()-st}")


var number = 0

function main()
{
    var base =  Module.findBaseAddress("test1.exe")
        
    if(base){
        Interceptor.attach(base.add(0x15C2), {//序号加1的位置
            onEnter: function(args) {
                number+=1;
            }
        });
        Interceptor.attach(base.add(0x15A8), {//程序报错的地址
            onEnter: function(args) {
                send(number);
            }
        });
        Interceptor.attach(base.add(0x15DC), {//成功的位置
            onEnter: function(args) {
                send(number);
            }
        });
        Interceptor.attach(base.add(0x2900), {//不让程序退出的太快!!直接hook掉puts函数
            onEnter: function (args) {
                // 延迟 10 秒钟
                var delay = 0x10;
                // console.log("Program is ending, delaying for " + (delay / 1000) + " seconds...");
                var start = new Date().getTime();
                while (new Date().getTime() < start + delay);
                // console.log("Delay complete.");
            }
        });

    }
}
setImmediate(main);

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值