免杀专题
27、花指令
1. 课程目标
学习花指令技术,通过插入垃圾代码干扰静态分析和特征匹配。
2. 名词解释
| 名词 | 英文 | 解释 |
|---|---|---|
| 花指令 | Junk Code / Garbage Code | 不影响程序逻辑的无用指令 |
| 死代码 | Dead Code | 永远不会执行的代码 |
| 不透明谓词 | Opaque Predicate | 结果恒定但难以分析的条件 |
3. 花指令类型
3.1 NOP填充
; 最简单的花指令
nop ; 90
nop
nop
; 多字节NOP
db 0x66, 0x90 ; xchg ax, ax
db 0x0F, 0x1F, 0x00 ; nop dword [eax]
3.2 等价指令替换
; 原始
mov eax, 0
; 等价替换
xor eax, eax
sub eax, eax
and eax, 0
; 原始
add eax, 1
; 等价替换
inc eax
sub eax, -1
lea eax, [eax+1]
3.3 死代码插入
; 永远不执行的代码
jmp real_code
db 'This is junk data...'
int 3
ret
real_code:
; 真正的代码
3.4 不透明谓词
// 结果恒为真,但静态分析难以判断
int x = GetTickCount();
if ((x * x) >= 0) { // 恒为真
// 真正代码
} else {
// 永远不执行的代码
ExitProcess(0);
}
4. 代码实现
4.1 C语言花指令宏
// 花指令宏
#define JUNK_CODE_1 \
__asm { push eax } \
__asm { xor eax, eax } \
__asm { add eax, 1 } \
__asm { sub eax, 1 } \
__asm { pop eax }
#define JUNK_CODE_2 \
__asm { pushfd } \
__asm { pushad } \
__asm { popad } \
__asm { popfd }
// 使用
void MyFunction() {
JUNK_CODE_1
// 真正代码
JUNK_CODE_2
}
4.2 x64内联汇编
由于MSVC x64不支持内联汇编,需要单独的.asm文件:
; junk.asm
.code
JunkCode proc
push rax
xor rax, rax
add rax, 12345678h
sub rax, 12345678h
pop rax
ret
JunkCode endp
end
4.3 自动花指令插入
// 随机插入花指令
void InsertJunkCode() {
volatile int junk = 0;
junk += GetTickCount() & 0xF;
junk ^= junk;
junk = junk * 2 - junk * 2;
}
#define JUNK InsertJunkCode();
void RealFunction() {
JUNK
// 代码1
JUNK
// 代码2
JUNK
}
5. 高级技术
5.1 跳转花指令
jmp label1
db 0xE8 ; call的操作码,会干扰反汇编
label1:
jmp label2
db 0xFF ; 无效操作码
label2:
; 真正代码
5.2 条件花指令
// 恒真条件
if (((unsigned int)-1) > 0) {
// 真正代码
}
// 恒假条件包裹垃圾代码
if (sizeof(int) > 100) {
MessageBoxA(NULL, "Never", "Never", 0);
}
6. 课后作业
6.1、作业1:手动花指令(必做)
- 在ShellCode Loader中插入花指令
- 观察对反汇编的影响
6.2、作业2:自动化(进阶)
- 编写花指令自动插入工具
- 随机化花指令内容
7. 下一课预告
下一课我们将学习花指令的剔除技术。