实验四:使用UPX加壳与脱壳
一、实验目的
-
了解程序加壳、脱壳原理 掌握PE文件结构 学习利用UPX Shell、LoardPE、IDA等工具完成软件的加、脱壳操作
二、实验题目
-
UPX加壳:对crackme加上UPX壳,用 LordPE 或 PEiD 工具查看加壳前后的变化 UPX脱壳:用UPX Unpacker对已加壳的 crackme.exe 程序进行脱壳 手动脱壳:使用ESP定律和Ollydbg工具对crackme.exe进行手工脱壳 IDA静态分析:用 IDA 的 F5 反汇编功能查看脱壳前后的程序伪代码,获取运行crackme后屏幕提示的输入口令
三、实验环境
-
Windows 7系统或以上、连接Internet的主机 可能会用到的软件:upxshell、LordPE、PEiD、upx unpacker、IDA、OllyDBG 手动脱壳实例参考:https://www.52pojie.cn/thread-727090-1-1.html ESP定律学习参考:https://www.52pojie.cn/thread-394116-1-1.html
四、实验步骤及结果
4.1 UPX加壳
首先查看未加壳前的应用程序
现在使用UPX Shell对壳进行加载
检查发现已经加壳成功
4.2 UPX脱壳
用UPX Unpacker对已加壳的 crackme.exe 程序进行脱壳
4.3 手动脱壳
根据ESP定律先找到PUSHAD下使得ESP变红的内存地址
然后在数据窗口中追踪
然后使用断点 --> 硬件访问 --> Word
然后使用F9直接运行到
然后再F8运行到OEP
然后删除硬件断点
然后使用Ollydbg脱壳工具进行脱壳
可以发现dump出来的文件脱壳成功
4.4 IDA静态分析
使用IDA打开脱壳后的文件可以看到main函数源代码
// write access to const memory has been detected, the output may be wrong! int main_0() { int v0; // ST14_4 int v1; // edx int result; // eax int v3; // ST14_4 int v4; // edx unsigned int i; // [esp+50h] [ebp-2Ch] char v6; // [esp+54h] [ebp-28h] char v7; // [esp+55h] [ebp-27h] char v8; // [esp+56h] [ebp-26h] char v9; // [esp+57h] [ebp-25h] char v10; // [esp+58h] [ebp-24h] char v11; // [esp+59h] [ebp-23h] char v12; // [esp+5Ah] [ebp-22h] char v13; // [esp+5Bh] [ebp-21h] char v14; // [esp+5Ch] [ebp-20h] char v15; // [esp+5Dh] [ebp-1Fh] char v16; // [esp+5Eh] [ebp-1Eh] char v17; // [esp+5Fh] [ebp-1Dh] int v18; // [esp+60h] [ebp-1Ch] int v19; // [esp+64h] [ebp-18h] char v20[20]; // [esp+68h] [ebp-14h] v6 = r; v7 = o; v8 = i; v9 = s; v10 = 2; v11 = 0; v12 = 1; v13 = 4; v14 = r; v15 = o; v16 = i; v17 = s; v18 = ; v19 = ; printf("password:"); scanf("%s", v20); if ( strlen(v20) == 12 ) { for ( i = 0; i < 0xC && *(&v6 + i) == v20[i]; ++i ) ; if ( i == 12 ) printf("good job! the key is your input! "); else printf("try again! "); if ( --stru_437180._cnt < 0 ) { _filbuf(&stru_437180); } else { v3 = (unsigned __int8)*stru_437180._ptr; ++stru_437180._ptr; } if ( --stru_437180._cnt < 0 ) { _filbuf(&stru_437180); } else { v4 = (unsigned __int8)*stru_437180._ptr; ++stru_437180._ptr; } result = 0; } else { printf("try again!! "); if ( --stru_437180._cnt < 0 ) { _filbuf(&stru_437180); } else { v0 = (unsigned __int8)*stru_437180._ptr; ++stru_437180._ptr; } if ( --stru_437180._cnt < 0 ) { _filbuf(&stru_437180); } else { v1 = (unsigned __int8)*stru_437180._ptr; ++stru_437180._ptr; } result = 0; } return result; }
程序是在与字符串rois2014rois进行比较,所以密码就是rois2014rois,测试成功