代碼混淆 - 花指令分析


萌新只會搞定一些特別簡單的花指令,而且還得靈光一閃才搞的定,今天來具體學習一下花指令相關內容

概念

花指令(或者叫臟字節)是企圖隱藏掉不想被逆向工程的代碼塊(或其它功能)的一種方法,在真實代碼中插入一些垃圾代碼的同時還保證原有程序的正確執行,而程序無法很好地反編譯, 難以理解程序內容,達到混淆視聽的效果。

簡單花指令及其原理

用ida舉例吧。我們用ida打開一個程序

我們看到,里面有代碼,有數據塊這些東西

但實際上,這並不是程序本身的樣子,我們可以選中一些代碼,按快捷鍵u(Undefined,取消定義)

這些代碼會變成一堆十六進制的單字節的數據,這才是程序本身的樣子

ida本身並不能區分什么是代碼什么是數據,它是通過某種算法來分析出一堆數據組合在一起是什么代碼。

讓這種分析算法出錯的最簡單的方法,就是花指令。

例如,下列匯編指令中,0xE8就是一個簡單花指令

addr:
	push ebp
	jz addr2
	jnz addr2
	db 0xE8
addr3:
	sub esp, 0x100
	add eax, 0x1
	sub ebx, 0xAFBC11
addr2:
	mov ebp, esp
	jmp addr3 

這種花指令的作用可以通過前面第一張圖片看到(第二張圖片可以看到里面插入了幾個E8,效果和這串代碼是一樣的):

  1. 出現了一坨紅色的、IDA分析不出來的數據(或者說,已經被錯誤分析的數據)
  2. 紅色的玩意后面,有一些數據沒有被分析成代碼,變成了一個數據塊,IDA認為他只是普通的數據
    這就是花指令的作用

我們來分析上面那串代碼

jz是結果為0就跳轉,jnz是結果不為0就跳轉,可以看成是if語句的2種分支
那一個條件只有真假兩種狀態,也就是說,不管條件如何,這里都會跳轉到addr2,那么,db 0xE8 這段東西就沒有卵用
但是,E8是call的機器碼,那么IDA會認為:如果不會jz/jnz跳轉的話,call(E8)就會使程序跳轉到一個新地址。這個地址就是下面的機器碼。

ida分析到jnz時會認為:如果他為0就不會跳轉了,但是事實上為0的時候會在jz跳轉,但是ida的算法處理不了這種情況
這串代碼中,ida會認為sub esp的一部分值是call的跳轉地址,此時就會出現如上方紅色數據的異常(根本沒有紅色數據這個地址)

然而,如果出題人經過精心設計,讓E8后的機器碼變成一個存在的地址,那么ida是不會報錯的。
這時我們就要這樣分析:例如上面那個紅色數據的地址是0x40101A,但是所有的call調用這個地址的時候都不是直接用0x40101A,而是諸如0x401019+1或者0x401018+2這種玩意,那么這里大概率有一個花指令。

這種花指令的應對方法就是按u

我們會看到一個XREF(非自然程序流程,可以用它對程序流進行跟蹤和控制,估計以后有的學了),關注到這一行,忽略掉上一行,選中XREF及之后沒有被分析的數據,然后按C轉換成代碼

這里優先用Analyze模式,如果Analyze分析錯了的話再用Force

這樣就恢復到了正常狀態。

另:這種花指令直接看匯編動調其實可以直接繞過去。

sp/esp analysis failed

IDA分析時,需要確認“代碼塊”和“數據塊”,並把代碼塊分析為函數
但是,這種分析過程需要對esp寄存器進行追蹤,一旦追蹤失敗便會報錯sp/esp analysis failed

一個簡單的概念:ret和jmp操作可以修改程序的執行流。ret是通過esp的指向來進行修改的,jmp是直接通過其后面的數字進行修改的。那么可以通過一些操作來讓ret當做jmp使用

比如這種main函數,你F5按壞了也不會反匯編成代碼

這個是源碼

#include <stdio.h>
#include <stdbool.h>
#pragma warning(disable:4996)
#include <stdlib.h>
void func1()
{
	__asm
	{
		lea eax, lab1;
		call eax;
		db 0xE8;
	lab1:
	}
	printf("func1\n");
}
void func2()
{
	__asm
	{
		cmp eax, ecx;
		jnz lab1;
		jz lab1;
		db 0xB8
	lab1: 
	}
	printf("func2\n");
}

這里我們用到了__asm代碼塊,簡單的說,這種內聯匯編的使用會讓ida錯誤地認為這里出現了函數嵌套函數的情況,導致不能用F5轉化為代碼。

這種情況下,我們關注一下有沒有紅色字體的XREF, 如果有的話再看看這種紅色字附近有沒有jz&jnz

上圖可以看到jnz short near ptr loc_40107E+1jz short near ptr loc_40107E+1

那我們找到地址40107E,然后按u

順便,我們還會發現:loc_40107E+1的+1沒了,變成了函數unk_40107F

然后從有XREF的這一行選中下面所有數據按C,首選Analyze,沒用再選Force

然后發現還真沒用,但是對這個奇怪的數據再按一下c

就沒問題了

腳本去除花指令

剛好大爹說暫時沒必要學,那充分必要地摸了(


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM