TransWikia.com

What's wrong with my mitm to support rr commands with gdbserver on IDA?

Reverse Engineering Asked on July 16, 2021

First of here is the gdb remote protocol doc.

The idea of the below script is the following – you enter an actual command (one that will be send as a direct packet see packets) in the gdb window then when you continue the process my command will be executed instead of the IDA vCont;s:1 or vCont;c. This so the IDA recognize the actual changes you have introduced by executing your command. Simply responding with “OK” after the qRcmd will not work for lets say stepping back because IDA wouldn’t ask for new register values.

I launch rr with rr replay -s 50505 -k, I attach with IDA to localhost:23946. Here is my mitm code (in 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("OKn"))
            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")

Basically what’s not working is that when i enter bs (step backwards one instruction packet) in the gdb monitor then press continue it’ll step backwards twice the first time and on the second it’ll run back to the beginning of the program.

One Answer

It turned out IDA sends first sends vCont;c and then vCont;s:1 for some weird reason in that particular instance. I fixed my 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(/^$Tdd/) != -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("OKn"))
            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")

I basically capture the last received signal and resend it the second time.

There is still a small issue when issuing a command when the program counter is on a break-point but that's small enough to ignore.

Answered by rec on July 16, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP