首页
社区
课程
招聘
[原创]PBCTF21 RE BinaryTree Beaengine+dijkstra解法
发表于: 2021-10-15 21:51 5967

[原创]PBCTF21 RE BinaryTree Beaengine+dijkstra解法

2021-10-15 21:51
5967

代码是动态解密的,简单的xor,解密一块执行一块。每一块结尾会设置rbx,rbx决定下一块被解密的代码。

实际上每一块代码相当于一个节点,里面有一个根据输入的jz,决定下一个rbx以及一个cost,所以相当于一颗二叉树。

每次经过一个节点都会累加cost。

根节点对应的代码块会判断cost是否小于等于某个值,然后输出成功信息。

如果只有唯一解那么显然是找最短路。

解题思路是beaengine解析代码生成图,用dijkstra算法求最短路并输出路径。
事实上只有一条最短路,刚刚等于那个值。

自己打oi时留下的板子,忘记有没有加优化了,不过这个版本比较方便记录path

 
 
 
 
 
#include <iostream>
#include <fstream>
#include <windows.h>
#include <queue>
#include <set>
#define BEA_ENGINE_STATIC
#include "BeaEngine.h"
#pragma comment(lib,"legacy_stdio_definitions.lib")
#pragma comment(lib, "BeaEngine.lib")
 
using namespace std;
 
typedef struct Block {
    int index;
    char buf[32];
};
 
int path[25503][4] = { 0, }; // 0(path/rbx,cost) 1(path/rbx,cost)
 
queue<pair<int, Block*>> rbxs; // rbx(xor offset), lastBlock
int sa = 0x176;
BYTE* firstBlock;
int blockNum = 0;
set<int> dised;
Block xorBlock = {
    0,
    0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x48,
    0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x48, 0xc7,
    0xc2, 0x05, 0x00, 0x00, 0x00, 0x49, 0x81, 0xf9,
    0xda, 0x49, 0x00, 0x00, 0x7f, 0x07, 0x4c, 0x89
};
 
Block* Xor(char* firstBlock, UInt64 offset, Block &oldBlock)
{
    Block* pB = new Block();
    pB->index = offset >> 5;
    blockNum++;
    char* xorBuf = firstBlock + offset;
    for (int i = 0; i < 32; i++) {
        pB->buf[i] = xorBuf[i] ^ oldBlock.buf[i];
    }
    return pB;
}
 
void Jmp(DISASM& infos)
{
    UINT64 nextVA = infos.Instruction.AddrValue;
    UINT64 curVA = infos.VirtualAddr;
 
    // jmp
    infos.EIP += nextVA - curVA;
    infos.VirtualAddr = nextVA;
}
 
void DisasmCode(char* stBuf, UINT64 stVA, Block* curBlock, int rbx, int branch)
{
    DISASM infos;
    size_t len;
 
    // init
    memset(&infos, 0, sizeof(DISASM));
    infos.EIP = (UINT64)stBuf;
    infos.VirtualAddr = (UINT64)stVA;
 
    while (infos.Error == 0) {
        // limit
        UInt64 offset = infos.EIP - (UINT64)curBlock->buf;
        if (offset < 0 || offset >= 32) {
            break;
        }
        if (infos.VirtualAddr == 0x400080) {// xor
            rbxs.push(make_pair(rbx, curBlock));
            break;
        }
 
 
        //disasm
        len = Disasm(&infos);
        cout << hex << infos.VirtualAddr << " " << infos.CompleteInstr << endl;
 
        // jmp
        if (infos.Instruction.BranchType == JmpType) {
            if (infos.Instruction.AddrValue == 0x400080) { // xor
                rbxs.push(make_pair(rbx, curBlock));
                break;
            }
 
            Jmp(infos);
        }
 
        // jmp
        if (infos.Instruction.BranchType) {
            // false branch
            DisasmCode((char*)(infos.EIP + len), infos.VirtualAddr + len, curBlock, rbx, 0);
            // true branch
            branch = 1;
            Jmp(infos);
            continue;
        }
 
        // if modified rbx (0x8)
        if (((infos.Operand1.AccessMode == WRITE) && (infos.Operand1.Registers.gpr & REG3))) {
            rbx += infos.Operand2.Memory.Displacement;
        }
 
        // if add r9 (0x200)
        if ((infos.Operand1.AccessMode == 3) && (infos.Operand1.Registers.gpr & 0x200)) {
            if (branch >= 0) {
                path[curBlock->index][branch * 2] = rbx >> 5;
                path[curBlock->index][branch * 2 + 1] = infos.Instruction.Immediat;
            }
        }
 
        // go on
        infos.EIP += len;
        infos.VirtualAddr += len;
    }
}
 
int main()
{
    ifstream fin;
    ofstream fout;
    BYTE* fileBuf;
    Block* lastBlock;
    Block* pB;
 
    // read file
 
    fin.open("E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main.elf", ios::in | ios::binary);
 
    fin.seekg(0, ios::end);
    size_t fileSize = fin.tellg();
    fin.seekg(0, ios::beg);
    fileBuf = (BYTE*)malloc(fileSize);
    fin.read((char*)fileBuf, fileSize);
 
    cout << "fileSize:" << dec << fileSize << endl;
    fin.close();
 
    // disasm
 
    firstBlock = fileBuf + sa;
 
    cout << "rbx:0" << endl;
    pB = Xor((char*)firstBlock, 0, xorBlock);
    dised.insert(0);
    DisasmCode(pB->buf, 0x4000AD, pB, 0, 0);
    while (!rbxs.empty()) {
        pair<int, Block*> t = rbxs.front();
        rbxs.pop();
 
        lastBlock = t.second;
 
        cout << "num:" << dec << blockNum << endl; // 0x639f * 2
 
        if (dised.insert(t.first).second) {
            // not disasm
            pB = Xor((char*)firstBlock, t.first, *lastBlock);
            // disasm
            DisasmCode(pB->buf, 0x4000AD, pB, 0, -1);
        }
    }
 
    // write file
 
    fout.open("E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main_.elf", ios::out | ios::binary);
    fout.write((char*)fileBuf, fileSize);
    fout.close();
 
    // write file
 
    fout.open("E:\\works\\ctf\\21pbctf\\re_BinaryTree\\path.txt", ios::out);
    for (int i = 0; i < blockNum; i++) {
        fout << path[i][0] << " " << path[i][1] << " " << path[i][2] << " " << path[i][3] << endl;
    }
    fout.close();
 
    fout.open("E:\\works\\ctf\\21pbctf\\re_BinaryTree\\pathDij.txt", ios::out);
    int E = 0;
    for (int i = 0; i < blockNum; i++) {
        if (path[i][1]) {
            fout << i << " " << path[i][0] << " " << path[i][1] << endl;
            fout << i << " " << path[i][2] << " " << path[i][3] << endl;
            E += 2;
        }
        else {
            cout << i << ",";
        }
    }
    cout << endl;
    fout.close();
 
    cout << "N E\n";
    cout << dec << blockNum << " " << E << endl;
    // 25503 50942 0
 
    return 0;
}
#include <iostream>
#include <fstream>
#include <windows.h>
#include <queue>
#include <set>
#define BEA_ENGINE_STATIC
#include "BeaEngine.h"
#pragma comment(lib,"legacy_stdio_definitions.lib")
#pragma comment(lib, "BeaEngine.lib")
 
using namespace std;
 
typedef struct Block {
    int index;
    char buf[32];
};
 
int path[25503][4] = { 0, }; // 0(path/rbx,cost) 1(path/rbx,cost)
 
queue<pair<int, Block*>> rbxs; // rbx(xor offset), lastBlock
int sa = 0x176;
BYTE* firstBlock;
int blockNum = 0;
set<int> dised;
Block xorBlock = {
    0,
    0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x48,
    0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x48, 0xc7,
    0xc2, 0x05, 0x00, 0x00, 0x00, 0x49, 0x81, 0xf9,
    0xda, 0x49, 0x00, 0x00, 0x7f, 0x07, 0x4c, 0x89
};
 
Block* Xor(char* firstBlock, UInt64 offset, Block &oldBlock)
{
    Block* pB = new Block();
    pB->index = offset >> 5;
    blockNum++;
    char* xorBuf = firstBlock + offset;
    for (int i = 0; i < 32; i++) {
        pB->buf[i] = xorBuf[i] ^ oldBlock.buf[i];
    }
    return pB;
}
 
void Jmp(DISASM& infos)
{
    UINT64 nextVA = infos.Instruction.AddrValue;
    UINT64 curVA = infos.VirtualAddr;
 
    // jmp
    infos.EIP += nextVA - curVA;
    infos.VirtualAddr = nextVA;
}
 
void DisasmCode(char* stBuf, UINT64 stVA, Block* curBlock, int rbx, int branch)
{
    DISASM infos;
    size_t len;
 
    // init
    memset(&infos, 0, sizeof(DISASM));
    infos.EIP = (UINT64)stBuf;
    infos.VirtualAddr = (UINT64)stVA;
 
    while (infos.Error == 0) {
        // limit
        UInt64 offset = infos.EIP - (UINT64)curBlock->buf;
        if (offset < 0 || offset >= 32) {
            break;
        }
        if (infos.VirtualAddr == 0x400080) {// xor
            rbxs.push(make_pair(rbx, curBlock));
            break;
        }
 
 
        //disasm
        len = Disasm(&infos);
        cout << hex << infos.VirtualAddr << " " << infos.CompleteInstr << endl;
 
        // jmp
        if (infos.Instruction.BranchType == JmpType) {
            if (infos.Instruction.AddrValue == 0x400080) { // xor
                rbxs.push(make_pair(rbx, curBlock));
                break;
            }
 
            Jmp(infos);
        }
 
        // jmp
        if (infos.Instruction.BranchType) {
            // false branch
            DisasmCode((char*)(infos.EIP + len), infos.VirtualAddr + len, curBlock, rbx, 0);
            // true branch
            branch = 1;
            Jmp(infos);
            continue;
        }
 
        // if modified rbx (0x8)
        if (((infos.Operand1.AccessMode == WRITE) && (infos.Operand1.Registers.gpr & REG3))) {
            rbx += infos.Operand2.Memory.Displacement;
        }
 
        // if add r9 (0x200)
        if ((infos.Operand1.AccessMode == 3) && (infos.Operand1.Registers.gpr & 0x200)) {
            if (branch >= 0) {
                path[curBlock->index][branch * 2] = rbx >> 5;
                path[curBlock->index][branch * 2 + 1] = infos.Instruction.Immediat;
            }
        }
 
        // go on
        infos.EIP += len;
        infos.VirtualAddr += len;
    }
}
 
int main()
{
    ifstream fin;
    ofstream fout;
    BYTE* fileBuf;
    Block* lastBlock;
    Block* pB;
 
    // read file
 
    fin.open("E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main.elf", ios::in | ios::binary);
 
    fin.seekg(0, ios::end);
    size_t fileSize = fin.tellg();
    fin.seekg(0, ios::beg);
    fileBuf = (BYTE*)malloc(fileSize);
    fin.read((char*)fileBuf, fileSize);
 
    cout << "fileSize:" << dec << fileSize << endl;
    fin.close();
 
    // disasm
 
    firstBlock = fileBuf + sa;
 
    cout << "rbx:0" << endl;
    pB = Xor((char*)firstBlock, 0, xorBlock);
    dised.insert(0);
    DisasmCode(pB->buf, 0x4000AD, pB, 0, 0);
    while (!rbxs.empty()) {
        pair<int, Block*> t = rbxs.front();
        rbxs.pop();
 
        lastBlock = t.second;
 
        cout << "num:" << dec << blockNum << endl; // 0x639f * 2
 
        if (dised.insert(t.first).second) {
            // not disasm
            pB = Xor((char*)firstBlock, t.first, *lastBlock);
            // disasm
            DisasmCode(pB->buf, 0x4000AD, pB, 0, -1);
        }
    }
 
    // write file
 
    fout.open("E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main_.elf", ios::out | ios::binary);
    fout.write((char*)fileBuf, fileSize);
    fout.close();
 
    // write file
 
    fout.open("E:\\works\\ctf\\21pbctf\\re_BinaryTree\\path.txt", ios::out);
    for (int i = 0; i < blockNum; i++) {
        fout << path[i][0] << " " << path[i][1] << " " << path[i][2] << " " << path[i][3] << endl;
    }

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-10-15 21:52 被wx_御史神风编辑 ,原因:
收藏
免费 2
支持
分享
最新回复 (1)
雪    币: 2466
活跃值: (4561)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不知道作者怎么写出来的
2021-10-16 07:51
0
游客
登录 | 注册 方可回帖
返回
//