我的 mitm 在 IDA 上支持带有 gdbserver 的 rr 命令有什么问题?

逆向工程 艾达 数据库 javascript 协议
2021-06-25 20:50:22

首先是gdb 远程协议文档

以下脚本的想法如下 - 您在 gdb 窗口中输入一个实际命令(一个将作为直接数据包发送,查看数据包)然后当您继续该过程时,将执行我的命令而不是 IDAvCont;s:1vCont;c. 这样 IDA 就能识别您通过执行命令引入的实际更改。在 qRcmd 之后简单地响应“OK”将不起作用,让我们说退后一步,因为 IDA 不会要求新的寄存器值。

我用 启动 rr rr replay -s 50505 -k,我用 IDA 附加到 localhost:23946。这是我的 mitm 代码(在 node.js 中):

const net=require("net")
const process = require('process');

net.createServer(server => {
    const client = new net.Socket()

    let lastcommand, response
    client.connect(50505, "localhost")

/**
 * @param {Buffer} string
 */
    function createResponse(string)
    {
        string = string.slice(0, string.length - 1)

        let checksum = 0 
        for(const a of string) checksum += a
        checksum %= 256
        return "$"+string.toString()+"#"+checksum.toString(0x10)
    }    

    client.on("data", handler = data => {
        let string = data.toString()

        console.log(string),
        server.write(string)
    })

    server.on("data", handlerserver = async data => {
        let string = data.toString()

        console.log(string)

        let cmd

        if((cmd = string.replace(/^\$qRcmd,([a-f0-9]+)#/, (_, substring) => substring)) != string){
            lastcommand = string = createResponse(Buffer.from(cmd, "hex"))
            const innerresponse = createResponse(Buffer.from("OK\n"))
            console.log(innerresponse)
            server.write(innerresponse)

            response = lastcommand


            return
        }
        else if(string.search(/^\$vCont;c#a8/) != -1 || string.search(/^\$vCont;s:1#23/) != -1) return console.log(response),
            client.write(response)//, response = undefined
        client.write(string)
    })
}).listen(23946, "localhost")

基本上不起作用的是,当我bs在 gdb 监视器中输入(后退一个指令包)然后按继续时,它第一次会后退两次,第二次它会跑回程序的开头。

1个回答

事实证明,在该特定情况下,IDA 首先发送vCont;c,然后vCont;s:1出于某种奇怪的原因发送我修复了我的 mitm :

const net=require("net")
const process = require('process');

net.createServer(server => {
    const client = new net.Socket()

    let lastcommand, response, lastterm
    client.connect(50505, "localhost")

/**
 * @param {Buffer} string
 */
    function createResponse(string)
    {
        string = string.slice(0, string.length - 1)

        let checksum = 0 
        for(const a of string) checksum += a
        checksum %= 256
        return "$"+string.toString()+"#"+checksum.toString(0x10)
    }    

    client.on("data", handler = data => {
        let string = data.toString()

        if(string.search(/^\$T\d\d/) != -1) lastterm = string

        console.log(string),
        server.write(string)
    })

    server.on("data", handlerserver = async data => {
        let string = data.toString()

        console.log(string)

        let cmd

        if((cmd = string.replace(/^\$qRcmd,([a-f0-9]+)#/, (_, substring) => substring)) != string){
            lastcommand = string = createResponse(Buffer.from(cmd, "hex"))
            const innerresponse = createResponse(Buffer.from("OK\n"))
            console.log(innerresponse)
            server.write(innerresponse)

            response = lastcommand


            return
        }
        else if(string.search(/^\$vCont;c#a8/) != -1) return console.log(response),
            client.write(response)//, response = undefined
        else if(string.search(/^\$vCont;s:1#23/) != -1) return console.log(lastterm), server.write(lastterm)
        client.write(string)
    })
}).listen(23946, "localhost")

我基本上捕获最后接收到的信号并第二次重新发送。

当程序计数器处于断点但小到可以忽略时,在发出命令时仍然存在一个小问题。