混淆IDA F5的一个小技巧-x64

2019-05-06 约 1283 字 预计阅读 3 分钟

声明:本文 【混淆IDA F5的一个小技巧-x64】 由作者 ret2nullptr 于 2019-05-06 08:30:00 首发 先知社区 曾经 浏览数 199 次

感谢 ret2nullptr 的辛苦付出!

本文没有归到反-反汇编系列中,因为主要是对抗IDA-F5,让函数的参数显示的很难看(没从网上看到过类似的思路,可能是我书读的比较少...分享一下心得)

本文介绍x64架构下的一个技巧,之后可能会研究一下x86架构下的对抗

不可否认的是,这些技巧都会在动态调试时露出真面目,但是配合反调试技巧,分析难度会加倍

失败尝试

代码如下:

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

int main(int argc, char** argv) {
    puts("nop me");
    puts("nop me");
    return 0;
}
//visual studio 2019 x64 release

打开IDA,再熟悉不过的流程...

因为是x64-fastcall,第一个参数被保存在了rcx中,既然rcx都是Str:"nop me",那么是否可以把第二次的lea rcx,Str直接nop掉呢?

patch后汇编如图:

F5后如图:

可以看到第二个puts(v3),只静态分析就不会得知输出什么了

运行崩溃

call puts("nop me")时的调试状况

rcx就是"nop me"的地址

再运行一下,rcx直接变成了0xFFFFFFFF

这样,运行到下一个puts(v3)时,程序就会因为非法的内存读而崩溃

原因

其实问题的根源很简单,rcx在函数内部被改掉了

跟进puts函数内部,前几条指令就已经破坏了原先的rcx

最后一行test rcx,rcx 直接把它清零了...

一些思考:

这里应该是因为rcx默认用来放函数的第一个参数,调用子函数时会破坏原先的rcx也属正常

但是,在父函数没有改变rcx时,是否就可以达到我们欺骗IDA的目的呢?

改进

源码

示例程序源码:

#define _CRT_SECURE_NO_WARNINGS

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

const char* s1 = "%s";
char buf[16];

int func() {
    //这里用返回类型为int,返回一个无用的0
    //主要是void时汇编层面一开始没调对,这样更轻松一点
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    puts("nop me");
    return 0;
}

int main(int argc, char** argv) {
    scanf(s1, buf);
    puts(buf);
    func();
    func();
    func();
    func();
    func();
    scanf(s1, buf);
    puts(buf);
    return 0;
}
//visual studio 2019 x64 release

程序中func()函数内写了这么多是不想让函数编译后被"内联"

func()调用这么多次也是出于这个原因

patch

main函数的逻辑如下:

我们的目的是隐藏第二个scanf("%s",buf)的参数,最好让F5的结果变成scanf(v3)这样

第一步

我们把func()的最后两个puts("nop me")直接nop掉,如图

这并不会破坏func()的堆栈之类,程序可以正确运行

第二步

main函数patch也不复杂,把第二个scanflea rcx,Format&lea rdx,bufnop掉即可

这样会改变程序流程,像刚才的失败一样,直接非法访问内存崩溃

第三步

我们在刚刚的func()函数中的一堆nop里做一些手脚,如下:

结果

F5后的结果如下,第二个scanf(v3)已经面目全非了,运行也不会报错

的确是两个scanf的效果,只是第二次scanf把上一次的\n吃掉了,看起来不对劲

实际上只要在第一个scanf后加上一个getchar()即可,放对位置也不会影响我们func()中藏的rcx&rdx

补充

复现可以直接拿源码编译,示例程序没有放在附件中...因为有时上传不成功比较尴尬

大佬轻喷,欢迎交流和指出错误和改进

关键词:[‘安全技术’, ‘二进制安全’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now