世上的唯美,是那雙清澈的眼眸 ——題記
以前看《自己動手寫操作系統(tǒng)》的時候,書中有段代碼改變了自身并且完成了正確的跳轉,這個想法實在漂亮(記得是從實模式跳轉到保護模式,晚了不去查了)。
但當時驚艷之后沒做深入考慮,這是個失誤。代碼可以改變自身,利用這點可以做一點簡陋的保護機制(代碼加密,當然也可以用于病毒程序)。但是估計保護效果
不會很好,下面分析一下卡巴斯基給出例子。
#include <windows.h>
#define CRYPT_LEN ((int)crypt_end - (int)for_crypt)
mark_begin()//用以標記,待加密函數(shù)在文件中的起始位置
{
__asm _emit 'K' __asm _emit 'P' __asm _emit 'N' __asm _emit 'C'
}
for_crypt(int a,int b)//待加密函數(shù)
{
return a + b;
}crypt_end(){}
mark_end()//用以標記,待加密函數(shù)在文件中的結束位置
{
__asm _emit 'K' __asm _emit 'P' __asm _emit 'N' __asm _emit 'C'
}
crypt_it(unsigned char *p,int c)//解密過程
{
int a;
VirtualProtect(p,c,PAGE_READWRITE,(DWORD*)&a);
for (a = 0;a < c; a++) *p++ ^=0x66;
VirtualProtect(p,c,PAGE_READONLY,(DWORD*)&a);
}
main()
{
crypt_it((unsigned char*)for_crypt,CRYPT_LEN);//調用解密函數(shù),解密被保護的代碼
printf("%02Xh\n",for_crypt(0x69,0x66));//函數(shù)運行結果
}
這個文件編譯連接完成后,肯定是沒法運行的。
加密工作是在編譯完之后,用十六進制編輯器修改兩個KPNC之間部分代碼(此處就是^=0x66的逆運算,簡單的XOR算法)。
當然完成之后兩個KPNC標志也要換成比較迷惑的數(shù)值,但這些都是徒勞的,沒法抵擋灰闊那雙清澈的眼眸。如果為了泄被破解之憤,大可以改成WOCA或者F.UCK等標志。
for (a = 0;a < c; a++) *p++ ^=0x66;試圖修改.text段,這回異常的。所以連接obj文件時加上選項/section:.text ERW指定具有讀寫和執(zhí)行屬性。
而Windows API VirtualProtect(p,c,PAGE_READWRITE,(DWORD*)&a);修改了被保護代碼的內存頁面屬性,指定為可讀寫。
這種保護對于靜態(tài)反匯編來說很容易制造混亂。但是在調試面前卻不堪一擊,那個API可是很顯眼啊。另外代碼段中多出一堆亂七八糟的東西也是很扎眼的。解密算法也較容易分析出來(及時算法復雜也只是時間問題)。不過跟反調試技術結合一下,應該有點用處。
只是玩味一下這個東西。
另外:也可以在堆棧中分配空間,那是可寫的,再把.text段中的負責“修改自身”的函數(shù)通過memcpy放到堆中,調用堆中的修改函數(shù)來改變自身代碼。雖然沒有異常,但是可能存在代碼重定位問題(畢竟代碼執(zhí)行的地址無法預知了)。