首页
社区
课程
招聘
[分享]一个IDA修复结构体负偏移的插件通过IDA MicroCode
发表于: 19小时前 170

[分享]一个IDA修复结构体负偏移的插件通过IDA MicroCode

19小时前
170

背景

在IDA中会遇到一个变量,先在一个正常的结构体加上一个offset, 然后访问offset前面字段时,再减去某个offset来访问,这个在正常的C语言代码里面,其实就是一个结构体,例如如在for循环这个结构中某个offset的频繁访问,经过编译器优化把这个频繁访问的字段单独定义成了一个变量,其他的字段就出现了负偏移的情况,当然也有其他情况,例如编译时使用了LLVM插件做混淆处理,也会出现。网上搜索了一圈,"IDA negative offset struct",没找到解决方案。现在通过IDA MicroCode微码做了一个简单的插件来解决这个问题。

案例

写了一个简单的C语言文件来复现这个情况:
fix_ida_negative_offset.c

#include <stdio.h>
#include <stdlib.h>

typedef struct Student {
    int id;
    int age;
    int score;
} Student;


int main()
{
    Student s1 = {
        1,
        17,
        80
    };
    Student* s = &s1;
    printf("id: %d, age: %d, score: %d\n", s->id, s->age, s->score);
    char* s2 = (char*)(void *)malloc(12);
    char *s3 = (char *)s2 + 8;
    *(int*)s3 = 90;
    *(int*)(s3 - 8) = 2;
    *(int*)(s3 - 4) = 18;
    s = (Student *)s2;
    printf("id: %d, age: %d, score: %d\n", s->id, s->age, s->score);
    free(s2);
}

使用gcc编译

gcc -o fix_ida_negative_offset fix_ida_negative_offset.c

拖到IDA里面看下:
图片描述
然后把Student结构体复制到IDA里面把v4和v5转换成Student结构休和Sutdent指针
图片描述
现在看由于v5变量被提前住后偏移了,导致出现这种负偏移的情况,伪代码字段名称也对不上,看着就比较影响代码语义。
*((_DWORD *)ptr + 2) = 90; // student->score = 90;
v5[-1].age = 2; // student->id = 2;
v5[-1].score = 18; // student->age = 18;
现在用选中v5插件操作一下
图片描述
操作完把变量名称改一下
图片描述
现在再看代码

  student2 = student;
  student->score = 90;
  student2->id = 2;
  student2->age = 18;

看起来是舒服多了。插件核心操作就是把原来的sutdent2 = (char *)student + 8;这句给改成了student2 = student;然后后面的偏移都减掉8就算完了。
不定义结构体的话,只修复偏移的话也是可以的,如图:
图片描述

插件源码

class MinsnVisitor(ida_hexrays.minsn_visitor_t):
    def __init__(self, varname):
        super().__init__()
        self.varname = varname
        self.num = 0

    def visit_minsn(self):
        if self.varname not in self.curins.dstr():
            return 0

        if self.curins.d.t == ida_hexrays.mop_l and self.curins.d.l.var().name == self.varname:
            if self.curins.l.t == ida_hexrays.mop_l and self.curins.l.l.var().name == self.varname:
                return 0
            if self.curins.r.t == ida_hexrays.mop_n:
                self.num = self.curins.r.nnn.value
                self.curins.r.nnn.value = 0
                return 0

        signed = 0
        if self.curins.opcode == ida_hexrays.m_add:
            signed = 1
        elif self.curins.opcode == ida_hexrays.m_sub:
            signed = -1

        if signed != 0:
            if self.curins.l.t == ida_hexrays.mop_l and self.curins.l.l.var().name == self.varname:
                if self.curins.d.t == ida_hexrays.mop_l and self.curins.d.l.var().name == self.varname:
                    return 0
                if self.curins.r.t == ida_hexrays.mop_n:
                    value = self.curins.r.nnn.value + (signed * self.num)
                    if value > 0:
                        self.curins.r.nnn.value = value
                    else:
                        self.curins.r.nnn.value = -value
                        self.curins.opcode = ida_hexrays.m_add
                    return 0

        return 0

主要是这部分代码,把这个偏移修复成0,然后记下来偏移的数值,后面再对应加减一个偏移即可。其他的是菜单和基本的IDA插件框架,当然持久化图省事用的json保存一个文件,从新打开时在当前目录读取这个json文件恢复。正确做法是使用ida_netnode API存储到 i64 文件里。

插件安装

把my_hexrays_plugin.py复制到IDA的plugins目录重启即可生效。

后记

插件主要使用MicroCode对偏移做修复,可以满足大部分简单的修复偏移情况,变量为先加4,后面把加8变成加12,插件也可修复成原来的加8的情况。


冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

注:下载本附件需支付 2雪币(note:2 points for downloading this attachment)
上传的附件:
收藏
免费 4
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回