逆向学习-SMC和花指令
花指令
动态保护:
反调试、反虚拟机
静态保护:
花指令、加密、加壳、混淆
反汇编原理:
线性扫描
递归行进算法
增加__declspec(naked),汇编指令只有这些
1 | __declspec(naked) |
0xe9是跳转指令,__emit 0xe9强行插入,在线性扫描时会错误识别,起到静态保护作用,递归行进算法能正常识别
成果骗过VS
IDA递归行进算法未骗过
IDA为递归行进算法,会到不同的分支,使用jz、jnz成功骗过
1 | __declspec(naked) |
实际运行,CPU永远不会来到这些错乱的地方
jz花指令,必定为0
1 | __declspec(naked) |
call
执行call指令需要将EIP压栈(EIP 寄存器保存着下一个要执行的指令的内存地址。换句话说,它指向 CPU 当前正在执行的指令序列中的下一个指令的位置。)
(ESP指向栈顶)
add dword PTR [esp], 7 ,栈顶+7,直接指向add eax,5
2+5
ret和call对应
call:压栈+跳转
ret:出栈+跳转(栈顶数据弹出,跳转执行)
在第一个
1 | __declspec(naked) |
地址计算
1 | section .text |
0XE8也可以代替0xE9
去除花指令手动:
IDA反汇编右键 undefined 快捷键U
正确入口右键code 快捷键C
自动去除:
把垃圾字节替换NOP 一个字节的0XE9
SMC
SMC:
Self modifying Code
代码自修改
在一段代码执行前,对其修改,一般用来加密核心功能逻辑,加壳技术基础 隐藏核心功能代码
1 | // SMCTest.cpp : 定义控制台应用程序的入口点。 |
思考
1、如何自动去除花指令
2、如何用汇编实现调用messageboxA
https://xz.aliyun.com/t/14580?time__1311=GqAhDKYK7Iox%2FtXeBKGQDktG8DgiT9tSYIeD
逆向题
IDA静态分析:
跟进数组,转换为array
将字节码复制出来,使用插件
https://github.com/P4nda0s/LazyIDA
插件报错修改
选中转换convert
1 | A1CE0256215723CA11EB71904C749A23222222AA760629AA76062DAA760634A976060E75914311DDAA66063EAA6E063FAA6E063CAA6E063DAA6E0602AA660603AA6E0600AA6E0601AA6E0606AA6E0607AA660604AA6E0605AA6E060AAA6E060BAA6E0608AA660609E466062E5AE466062F57AA7E062CE46606325BE466063357AA7E0630E46606360FE466063758E46606344AE46606354BE466063A44E466063B47E466063945A9D01A28562F21D221DA1A2C57DAA1DD32562B7D7C10E279A1E602E17211E2A7E25623CB7AAF56062EAF5E063E09D009D877C921AF6B222D9C3E342D9C0809C92D943E3519C9573321EA21F2A1DB325EC47F7D7C79A1E602E1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
convert hex string
Winhex => 右键编辑=> 剪切板数据 => 写入
这种直接在IDA读取的字节码是经过异或加密的需要先进行解密
1 | // shellcode解密.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 |
使用IDA打开二进制exe,发现E8疑似花指令
对E8字节码使用undefined,33字节码使用code
无法F5翻译成伪代码,对汇编进行人工翻译
栈为先进先出,所以存在字符串
xuanyuan-zhifeng
后面IDA有点分析不下去了,使用x32dbg进行动态分析
使用字符串查找定位到flag
第一个关键点比较输入字符长度是否等于16
关键点2:
我输入的为16个1
ebx=x ebp=1
1-x
ebx=1
又将1-x和1进行比较,也就是我们输入-真正的字符=1进行比较,如果不相等程序直接会崩溃
接下来第一个字符输入y满足条件,继续看程序运行,debug到这个位置,有个cmp ecx,10是个循环,换算10进制为16次
第二次是我输入的1和u相减,最好和0比较,若不等则程序崩溃
再次输入flag=yu11111111111111,找到了比较规律,比较的就是上面这段数组
1 | ds:[edi + edx] = 0 + 0095FB1A = 0095FB1A |
规律为输入字符按顺序减去xuanyuan-zhifeng的字母,结果和数组中的数组进行对比
1 | x u a n y u a n - z h i f e n g |
__END__