没想到拖了这么久哈哈哈哈,最近忙着工作和论文还有答辩(绝对不是我懒,绝对不是),最近因为一些原因马上要失业了,难道这就是不更新的代价吗!!不要啊!!!。废话不多说开始
ASP2.12分析
环境准备
xdbg、asp2.12壳文件、ida
首先进入xdbg调试asp文件分析
00405001 |跳转到40500E
0040500A | 5D | pop ebp |
0040500B | 45 | inc ebp |
0040500C

image-20250502232205704.png (36.37 KB, 下载次数: 0)
下载附件
2025-5-24 17:35 上传
当第一次进来的时候可能是这样的,在进入call时的机器码发现不是在首位上,为了便于观察,我们只需要如图操作

image-20250502232437471.png (192.63 KB, 下载次数: 0)
下载附件
2025-5-24 17:36 上传
选中该包含该地址的代码,如图点击,然后在选择要跳转的地址,按相同的步骤,选择code(1字节上面的)就可以了
0040500E
这里的操作是载入kernel32.dll中的VirtuslAlloc和VirtualFree这两个函数。
0040508A | 8B9D 31050000 | mov ebx,dword ptr ss:[ebp+531] | 设置为0,暂时没发现作用
00405090 | 0BDB | or ebx,ebx |
00405092 | 74 0A | je capturescreen.40509E |
00405094 | 8B03 | mov eax,dword ptr ds:[ebx] |
00405096 | 8785 35050000 | xchg dword ptr ss:[ebp+535],eax | ebp+535:sub_40553E+A
0040509C | 8903 | mov dword ptr ds:[ebx],eax |
0040509E | 8DB5 69050000 | lea esi,dword ptr ss:[ebp+569] | 各区段的RVA和Size信息
004050A4 | 833E 00 | cmp dword ptr ds:[esi],0 | esi:sub_40553E+5E
004050A7 | 0F84 21010000 | je capturescreen.4051CE |
004050AD | 6A 04 | push 4 |
004050AF | 68 00100000 | push 1000 | 内存分配的类型MEM_COMMIT
004050B4 | 68 00180000 | push 1800 | 内存分配的大小
004050B9 | 6A 00 | push 0 |
004050BB | FF95 4D050000 | call dword ptr ss:[ebp+54D] | 调用VirtualAlloc
004050C1 | 8985 56010000 | mov dword ptr ss:[ebp+156],eax | 分配内存的起始地址为5B0000
004050C7 | 8B46 04 | mov eax,dword ptr ds:[esi+4] | 读取区段的大小
004050CA | 05 0E010000 | add eax,10E |
004050CF | 6A 04 | push 4 |
004050D1 | 68 00100000 | push 1000 |
004050D6 | 50 | push eax | 内存分配的大小
004050D7 | 6A 00 | push 0 |
004050D9 | FF95 4D050000 | call dword ptr ss:[ebp+54D] | 调用VirtualAlloc
004050DF | 8985 52010000 | mov dword ptr ss:[ebp+152],eax | 内存分配的起始地址
004050E5 | 56 | push esi | esi:sub_40553E+5E
004050E6 | 8B1E | mov ebx,dword ptr ds:[esi] | esi:sub_40553E+5E
004050E8 | 039D 22040000 | add ebx,dword ptr ss:[ebp+422] |
004050EE | FFB5 56010000 | push dword ptr ss:[ebp+156] | 分配的内存地址
004050F4 | FF76 04 | push dword ptr ds:[esi+4] | esi+4:sub_40553E+62
004050F7 | 50 | push eax | 缓存的地址
004050F8 | 53 | push ebx | 区段地址
004050F9 | E8 6E050000 | call capturescreen.40566C | 解密函数,返回的是大小
004050FE | B3 01 | mov bl,1 |
00405100 | 80FB 00 | cmp bl,0 | 判断是否是代码段
00405103 | 75 5E | jne capturescreen.405163 |
00405105 | FE85 EC000000 | inc byte ptr ss:[ebp+EC] | 代码段标识+1
0040510B | 8B3E | mov edi,dword ptr ds:[esi] | esi:sub_40553E+5E
0040510D | 03BD 22040000 | add edi,dword ptr ss:[ebp+422] |
00405113 | FF37 | push dword ptr ds:[edi] | 无意义代码开始
00405115 | C607 C3 | mov byte ptr ds:[edi],C3 |
00405118 | FFD7 | call edi |
0040511A | 8F07 | pop dword ptr ds:[edi] | 无意义代码结束
0040511C | 50 | push eax |
0040511D | 51 | push ecx |
0040511E | 56 | push esi | esi:sub_40553E+5E
0040511F | 53 | push ebx |
00405120 | 8BC8 | mov ecx,eax |
00405122 | 83E9 06 | sub ecx,6 |
00405125 | 8BB5 52010000 | mov esi,dword ptr ss:[ebp+152] | esi:sub_40553E+5E, ebp+152:sub_405071+F4
0040512B | 33DB | xor ebx,ebx |
0040512D | 0BC9 | or ecx,ecx |
0040512F | 74 2E | je capturescreen.40515F |
00405131 | 78 2C | js capturescreen.40515F |
00405133 | AC | lodsb | 从si寄存器按对应字节累计读入eax寄存器,读入后si就增加或者减少,即对缓存地址里的数据进行还原
00405134 | 3C E8 | cmp al,E8 | 寻找E8,找call
00405136 | 74 0A | je capturescreen.405142 |
00405138 | EB 00 | jmp capturescreen.40513A |
0040513A | 3C E9 | cmp al,E9 | 寻找E9,找jmp
0040513C | 74 04 | je capturescreen.405142 |
0040513E | 43 | inc ebx |
0040513F | 49 | dec ecx |
00405140 | EB EB | jmp capturescreen.40512D |
00405142 | 8B06 | mov eax,dword ptr ds:[esi] | 读取跳转后的4字节
00405144 | EB 00 | jmp capturescreen.405146 |
00405146 | 803E 01 | cmp byte ptr ds:[esi],1 | 判断是否为1,不是则跳过修复
00405149 | 75 F3 | jne capturescreen.40513E |
0040514B | 24 00 | and al,0 | 后面就是开始修复的操作,之后就是重新开始遍历寻找E8和E9
0040514D | C1C0 18 | rol eax,18 | 循环左移
00405150 | 2BC3 | sub eax,ebx |
00405152 | 8906 | mov dword ptr ds:[esi],eax | esi:sub_40553E+5E
00405154 | 83C3 05 | add ebx,5 |
00405157 | 83C6 04 | add esi,4 | esi:sub_40553E+5E
0040515A | 83E9 05 | sub ecx,5 |
0040515D | EB CE | jmp capturescreen.40512D |
0040515F | 5B | pop ebx |
00405160 | 5E | pop esi | esi:sub_40553E+5E
00405161 | 59 | pop ecx |
00405162 | 58 | pop eax |
00405163 | EB 08 | jmp capturescreen.40516D |
00405165 | 0000 | add byte ptr ds:[eax],al |
00405167 | 58 | pop eax |
00405168 | 0000 | add byte ptr ds:[eax],al |
0040516A | 0049 00 | add byte ptr ds:[ecx],cl |
0040516D | 8BC8 | mov ecx,eax |
0040516F | 8B3E | mov edi,dword ptr ds:[esi] | esi:sub_40553E+5E
00405171 | 03BD 22040000 | add edi,dword ptr ss:[ebp+422] | 区段地址
00405177 | 8BB5 52010000 | mov esi,dword ptr ss:[ebp+152] | 缓存地址
0040517D | C1F9 02 | sar ecx,2 | 算术右移
00405180 | F3:A5 | rep movsd |
00405182 | 8BC8 | mov ecx,eax |
00405184 | 83E1 03 | and ecx,3 |
00405187 | F3:A4 | rep movsb |
00405189 | 5E | pop esi | esi:sub_40553E+5E
0040518A | 68 00800000 | push 8000 | MEM_RELEASE属性
0040518F | 6A 00 | push 0 |
00405191 | FFB5 52010000 | push dword ptr ss:[ebp+152] | 传入缓存地址
00405197 | FF95 51050000 | call dword ptr ss:[ebp+551] | 调用VirtualFree函数
0040519D | 83C6 08 | add esi,8 | esi:sub_40553E+5E
004051A0 | 833E 00 | cmp dword ptr ds:[esi],0 | esi:sub_40553E+5E
004051A3 | 0F85 1EFFFFFF | jne capturescreen.4050C7 | 判断区段是否还有区段的RVA和Size
004051A9 | 68 00800000 | push 8000 |
004051AE | 6A 00 | push 0 |
004051B0 | FFB5 56010000 | push dword ptr ss:[ebp+156] | ebp+156:sub_405071+F8
004051B6 | FF95 51050000 | call dword ptr ss:[ebp+551] |
004051BC | 8B9D 31050000 | mov ebx,dword ptr ss:[ebp+531] | ebp+531:sub_40553E+6
004051C2 | 0BDB | or ebx,ebx |
004051C4 | 74 08 | je capturescreen.4051CE |
004051C6 | 8B03 | mov eax,dword ptr ds:[ebx] |
004051C8 | 8785 35050000 | xchg dword ptr ss:[ebp+535],eax | ebp+535:sub_40553E+A
这里的操作是对节区的还原处理操作,对.text区段、.data区段和.rsrc区段进行处理,text区段有对call和jmp代码进行还原的操作,每当调用解密函数时,数据就会被写入缓存地址,然后通过rep movsb,来写入原本的区段地址。这里可以被分为两个部分来处理,一个是处理代码段,;另一个处理非代码段。
004051CE | 8B95 22040000 | mov edx,dword ptr ss:[ebp+422] |
004051D4 | 8B85 2D050000 | mov eax,dword ptr ss:[ebp+52D] | 这个基地址我不知道是怎么得到的,读取文件16进制也是这么多
004051DA | 2BD0 | sub edx,eax | 看文章说是判断下当前的ImageBase 决定是否要进行重定位
004051DC | 74 79 | je capturescreen.405257 |
004051DE | 8BC2 | mov eax,edx | 下面是重定位的处理,由于没遇见过,所以就没有分析了
004051E0 | C1E8 10 | shr eax,10 | eax:"USER32.dll"
004051E3 | 33DB | xor ebx,ebx |
004051E5 | 8BB5 39050000 | mov esi,dword ptr ss:[ebp+539] | ebp+539:sub_40553E+E
004051EB | 03B5 22040000 | add esi,dword ptr ss:[ebp+422] |
004051F1 | 833E 00 | cmp dword ptr ds:[esi],0 | esi:"`("
004051F4 | 74 61 | je capturescreen.405257 |
004051F6 | 8B4E 04 | mov ecx,dword ptr ds:[esi+4] |
004051F9 | 83E9 08 | sub ecx,8 |
004051FC | D1E9 | shr ecx,1 |
004051FE | 8B3E | mov edi,dword ptr ds:[esi] | esi:"`("
00405200 | 03BD 22040000 | add edi,dword ptr ss:[ebp+422] |
00405206 | 83C6 08 | add esi,8 | esi:"`("
00405209 | 66:8B1E | mov bx,word ptr ds:[esi] | esi:"`("
0040520C | C1EB 0C | shr ebx,C |
0040520F | 83FB 01 | cmp ebx,1 |
00405212 | 74 0C | je capturescreen.405220 |
00405214 | 83FB 02 | cmp ebx,2 |
00405217 | 74 16 | je capturescreen.40522F |
00405219 | 83FB 03 | cmp ebx,3 |
0040521C | 74 20 | je capturescreen.40523E |
0040521E | EB 2C | jmp capturescreen.40524C |
00405220 | 66:8B1E | mov bx,word ptr ds:[esi] | esi:"`("
00405223 | 81E3 FF0F0000 | and ebx,FFF |
00405229 | 66:01041F | add word ptr ds:[edi+ebx],ax |
0040522D | EB 1D | jmp capturescreen.40524C |
0040522F | 66:8B1E | mov bx,word ptr ds:[esi] | esi:"`("
00405232 | 81E3 FF0F0000 | and ebx,FFF |
00405238 | 66:01141F | add word ptr ds:[edi+ebx],dx |
0040523C | EB 0E | jmp capturescreen.40524C |
0040523E | 66:8B1E | mov bx,word ptr ds:[esi] | esi:"`("
00405241 | 81E3 FF0F0000 | and ebx,FFF |
00405247 | 01141F | add dword ptr ds:[edi+ebx],edx |
0040524A | EB 00 | jmp capturescreen.40524C |
0040524C | 66:830E FF | or word ptr ds:[esi],FFFF | esi:"`("
00405250 | 83C6 02 | add esi,2 | esi:"`("
00405253 | E2 B4 | loop capturescreen.405209 |
00405255 | EB 9A | jmp capturescreen.4051F1 |
。重定位的操作
00405257 | 8B95 22040000 | mov edx,dword ptr ss:[ebp+422] |
0040525D | 8BB5 41050000 | mov esi,dword ptr ss:[ebp+541] | ebp+541:sub_40553E+16
00405263 | 0BF6 | or esi,esi | esi:"`("
00405265 | 74 11 | je capturescreen.405278 |
00405267 | 03F2 | add esi,edx | esi:"`("
00405269 | AD | lodsd |
0040526A | 0BC0 | or eax,eax | eax:"USER32.dll"
0040526C | 74 0A | je capturescreen.405278 |
0040526E | 03C2 | add eax,edx | eax:"USER32.dll"
00405270 | 8BF8 | mov edi,eax | eax:"USER32.dll"
00405272 | 66:AD | lodsw |
00405274 | 66:AB | stosw |
00405276 | EB F1 | jmp capturescreen.405269 |
00405278 | BE 08260000 | mov esi,2608 | 获取原本导入表的RVA,这里猜测是通过解密函数来实现这种静态获取的
0040527D | 8B95 22040000 | mov edx,dword ptr ss:[ebp+422] |
00405283 | 03F2 | add esi,edx | esi:"`("
00405285 | 8B46 0C | mov eax,dword ptr ds:[esi+C] | 获取导入表中的dll名称的RVA
00405288 | 85C0 | test eax,eax | eax:"USER32.dll"
0040528A | 0F84 0A010000 | je capturescreen.40539A |
00405290 | 03C2 | add eax,edx | eax:"USER32.dll"
00405292 | 8BD8 | mov ebx,eax | eax:"USER32.dll"
00405294 | 50 | push eax | eax:"USER32.dll"
00405295 | FF95 4D0F0000 | call dword ptr ss:[ebp+F4D] | 调用GetModuleHandle函数
0040529B | 85C0 | test eax,eax | eax:"USER32.dll"
0040529D | 75 07 | jne capturescreen.4052A6 | 如果获取失败,则用loadlibiraryA来导入
0040529F | 53 | push ebx |
004052A0 | FF95 510F0000 | call dword ptr ss:[ebp+F51] | ebp+F51:sub_405F3C+28
004052A6 | 8985 45050000 | mov dword ptr ss:[ebp+545],eax | ebp+545:sub_40553E+1A
004052AC | C785 49050000 0000 | mov dword ptr ss:[ebp+549],0 | ebp+549:sub_40553E+1E
004052B6 | 8B95 22040000 | mov edx,dword ptr ss:[ebp+422] | 取出基地址Imagebase
004052BC | 8B06 | mov eax,dword ptr ds:[esi] | 取OriginalFirstThunk值
004052BE | 85C0 | test eax,eax | 如果为0的话就取FirstThunk
004052C0 | 75 03 | jne capturescreen.4052C5 |
004052C2 | 8B46 10 | mov eax,dword ptr ds:[esi+10] | eax:"USER32.dll"
004052C5 | 03C2 | add eax,edx | eax:"USER32.dll"
004052C7 | 0385 49050000 | add eax,dword ptr ss:[ebp+549] | 加上偏移
004052CD | 8B18 | mov ebx,dword ptr ds:[eax] | eax:"USER32.dll"
004052CF | 8B7E 10 | mov edi,dword ptr ds:[esi+10] | 取FirstThunk
004052D2 | 03FA | add edi,edx |
004052D4 | 03BD 49050000 | add edi,dword ptr ss:[ebp+549] | 加上偏移
004052DA | 85DB | test ebx,ebx |
004052DC | 0F84 A2000000 | je capturescreen.405384 |
004052E2 | F7C3 00000080 | test ebx,80000000 | 判断是不是序号导入
004052E8 | 75 04 | jne capturescreen.4052EE |
004052EA | 03DA | add ebx,edx |
004052EC | 43 | inc ebx |
004052ED | 43 | inc ebx | 获取到函数名
004052EE | 53 | push ebx | 保存ebx
004052EF | 81E3 FFFFFF7F | and ebx,7FFFFFFF | 去掉最高位
004052F5 | 53 | push ebx |
004052F6 | FFB5 45050000 | push dword ptr ss:[ebp+545] | 当前dll的句柄
004052FC | FF95 490F0000 | call dword ptr ss:[ebp+F49] | 调用GetProcAdrress函数
00405302 | 85C0 | test eax,eax | eax:"USER32.dll"
00405304 | 5B | pop ebx | 返回原来的ebx
00405305 | 75 6F | jne capturescreen.405376 | 成功返回就跳走
00405307 | F7C3 00000080 | test ebx,80000000 |
0040530D | 75 19 | jne capturescreen.405328 |
0040530F | 57 | push edi |
00405310 | 8B46 0C | mov eax,dword ptr ds:[esi+C] | eax:"USER32.dll", esi+C:"n*"R32.dll"
00405313 | 0385 22040000 | add eax,dword ptr ss:[ebp+422] |
00405319 | 50 | push eax | eax:"USER32.dll"
0040531A | 53 | push ebx |
0040531B | 8D85 75040000 | lea eax,dword ptr ss:[ebp+475] |
00405321 | 50 | push eax | eax:"USER32.dll"
00405322 | 57 | push edi |
00405323 | E9 98000000 | jmp capturescreen.4053C0 |
00405328 | 81E3 FFFFFF7F | and ebx,7FFFFFFF |
0040532E | 8B85 26040000 | mov eax,dword ptr ss:[ebp+426] |
00405334 | 3985 45050000 | cmp dword ptr ss:[ebp+545],eax | ebp+545:sub_40553E+1A
0040533A | 75 24 | jne capturescreen.405360 |
0040533C | 57 | push edi |
0040533D | 8BD3 | mov edx,ebx |
0040533F | 4A | dec edx |
00405340 | C1E2 02 | shl edx,2 |
00405343 | 8B9D 45050000 | mov ebx,dword ptr ss:[ebp+545] | ebp+545:sub_40553E+1A
00405349 | 8B7B 3C | mov edi,dword ptr ds:[ebx+3C] |
0040534C | 8B7C3B 78 | mov edi,dword ptr ds:[ebx+edi+78] |
00405350 | 035C3B 1C | add ebx,dword ptr ds:[ebx+edi+1C] |
00405354 | 8B0413 | mov eax,dword ptr ds:[ebx+edx] | eax:"USER32.dll"
00405357 | 0385 45050000 | add eax,dword ptr ss:[ebp+545] | ebp+545:sub_40553E+1A
0040535D | 5F | pop edi |
0040535E | EB 16 | jmp capturescreen.405376 |
00405360 | 57 | push edi |
00405361 | 8B46 0C | mov eax,dword ptr ds:[esi+C] | eax:"USER32.dll", esi+C:"n*"R32.dll"
00405364 | 0385 22040000 | add eax,dword ptr ss:[ebp+422] |
0040536A | 50 | push eax | eax:"USER32.dll"
0040536B | 53 | push ebx |
0040536C | 8D85 C6040000 | lea eax,dword ptr ss:[ebp+4C6] |
00405372 | 50 | push eax | eax:"USER32.dll"
00405373 | 57 | push edi |
00405374 | EB 4A | jmp capturescreen.4053C0 |
00405376 | 8907 | mov dword ptr ds:[edi],eax | 返回的函数地址写进IAT
00405378 | 8385 49050000 04 | add dword ptr ss:[ebp+549],4 | 循环填IAT
0040537F | E9 32FFFFFF | jmp capturescreen.4052B6 |
00405384 | 8906 | mov dword ptr ds:[esi],eax | esi:"`(", eax:"USER32.dll"
00405386 | 8946 0C | mov dword ptr ds:[esi+C],eax | esi+C:"n*", eax:"USER32.dll"
00405389 | 8946 10 | mov dword ptr ds:[esi+10],eax | eax:"USER32.dll"
0040538C | 83C6 14 | add esi,14 | 下一个dll
0040538F | 8B95 22040000 | mov edx,dword ptr ss:[ebp+422] |
00405395 | E9 EBFEFFFF | jmp capturescreen.405285 |
这里是为原来的PE导入IAT
0040539A | B8 10190000 | mov eax,1910 | 原PE文件的入口点
0040539F | 50 | push eax |
004053A0 | 0385 22040000 | add eax,dword ptr ss:[ebp+422] | 换成VA
004053A6 | 59 | pop ecx | ecx:EntryPoint
004053A7 | 0BC9 | or ecx,ecx | ecx:EntryPoint
004053A9 | 8985 A8030000 | mov dword ptr ss:[ebp+3A8],eax |把入口点存入[ebp+3A8]里,在查找以下这个地址就是下面push 0中0的地址
004053AF | 61 | popad | 返回壳之前的状态
004053B0 | 75 08 | jne capturescreen.4053BA |
004053B2 | B8 01000000 | mov eax,1 |
004053B7 | C2 0C00 | ret C |
004053BA | 68 10194000 | push capturescreen.401910 |这里本来是push 0,然后通过地址0x4053A9动态修改,从而实现跳转到真正的入口点
004053BF | C3 | ret | 跳转到真正的入口点
通过动态修改地址内容,跳转到真正的入口点
至此asp2.12壳浅层分析完毕,这里还没有去分析解密函数内部的内容。
在参考文章中,都是把解密函数用IDA把解密函数给抠出来,编译为obj使用的
接下来就是代码的分析,我把我认为的困难的部分给拎出来单独说一下
首先就是
if(pTemp.VirtualAddress AddressOfEntryPoint
&& (pTemp.VirtualAddress + pTemp.Misc.VirtualSize) > newOptHead->AddressOfEntryPoint)
{
packaddr = (LPBYTE)(pImageBase + pTemp.PointerToRawData + 0x57c);//0x57c是加密数据的偏移
//修正解压函数地址
g_esi = (DWORD)(pNewPe + pTemp.VirtualAddress + 0x70E - 0x44403E);
//修正OEP
DWORD dwOEP = *(DWORD*)(pNewPe + pTemp.VirtualAddress + 0x39b);
newOptHead->AddressOfEntryPoint = dwOEP;
//修正导入表数据目录
DWORD dwIAT = *(DWORD*)(pNewPe + pTemp.VirtualAddress + 0x279);
newOptHead->DataDirectory[1].VirtualAddress = dwIAT;
//取出地址表异或值
bXorVal = *(BYTE*)(pNewPe + pTemp.VirtualAddress + 0x148);
//地址表是否参与异或运算
isXor = *(BYTE*)(pNewPe + pTemp.VirtualAddress + 0x145) > 0 ? 0 : 1;
}
首先看packaddr,这个指针是加密区段的内存偏移,这里是通过文件偏移来读取区段的偏移地址。去下图,0x1A00 + 0x57C = 0x1F7C,0x1A00是.aspack区段的文件偏移地址。

image-20250522215641433.png (14.52 KB, 下载次数: 0)
下载附件
2025-5-24 17:37 上传
那0x57C又是怎么来的呢?这里先回到调试器中,看到0x40509E地址,这里就把各区段的RVA和Size存在esi寄存器中,把[ebp + 569]地址转到内存中,如下图的内存1这里的偏移的地址就是0x57C

image-20250522220115611.png (125.05 KB, 下载次数: 0)
下载附件
2025-5-24 17:37 上传
接下来就是g_esi,这个是解密函数里需要用到的,在调试器中如下图

image-20250524001504251.png (10.97 KB, 下载次数: 0)
下载附件
2025-5-24 17:37 上传

image-20250522223554308.png (97.02 KB, 下载次数: 0)
下载附件
2025-5-24 17:38 上传
在解密函数中都会有调用0x405C96,而0x405C96这个函数每次都会返回给esi这个寄存器固定的值,这里的常量与代码中的不一样,但经过调试,得出的结果是一样的,我这里是0x405C9B - 0x4445CB = 0xFFFC16D0,得到exi后进行下一个代码,从0x40570E开始以eax为偏移获取后续的数据,由于基址为0x40000,所以偏移量为0x570E,因此代码中是求esi,通过恒等式移项就可以,即 esi + 0x44403E = 基址 + 0x570E ==> esi = 基址 + 0x570E - 0x44403E

image-20250524002346214.png (36.8 KB, 下载次数: 0)
下载附件
2025-5-24 17:38 上传
接下来是OEP,只需要注意代码中的数据,如图

image-20250524004139212.png (107.45 KB, 下载次数: 0)
下载附件
2025-5-24 17:38 上传
标灰的地方就是OEP的RVA了,所以直接读取该数据所在的RVA的地址了
下面的导入表的修正也是同样的道理,直接贴图就不细说了

image-20250524004427530.png (142.13 KB, 下载次数: 0)
下载附件
2025-5-24 17:39 上传
下面是jmp/call指令还原的条件判断,但是文章说
jmp/CALL后面的第一个字节为还原条件,针对不同的程序,判断条件不同
因此可能有dll之类不同的分类,总之在当前情况下就是还原条件,后面会详说
接下来就是还原跳转指令了,如图中的0x405133地址的代码,解密函数中的参数就有缓存地址,因此执行解密函数后,缓存地址就是需要还原的数据,代码中fixCode函数中的 char *addrbuff 参数好像没有用处。下面的代码就是修复的操作,根据汇编语言来写成高级语言

image-20250524111909689.png (89.11 KB, 下载次数: 0)
下载附件
2025-5-24 17:39 上传
然后我认为代码中比较难理解的部分我就分析完了,接下来是提取ida中代码编译成obj文件的操作说明

image-20250524164532888.png (81.82 KB, 下载次数: 0)
下载附件
2025-5-24 17:39 上传
首先载入IDA找到解密函数的地址,这里我把这个进行了函数处理,就是把这个当成函数来看待,从而生成函数相关的栈帧、参数、局部变量之类的。
然后把这函数全都复制出来,粘贴到asm文件,再用masm执行编译为obj文件的命令,由于我这边没有masm环境,想尝试的可以自行尝试和搜索资料。这里不仅仅只复制解密函数,还需要复制以前的代码,也就是call里面的代码。
至此asp分析完毕。
附件:
asp代码和测试文件.rar
(16.28 KB, 下载次数: 2)
2025-5-24 17:49 上传
点击文件名下载附件
下载积分: 吾爱币 -1 CB
参考资料:
[AsPack 2.12 分析及静态脱壳机编写,附源码]([原创]AsPack 2.12 分析及静态脱壳机编写,附源码-加壳脱壳-看雪-安全社区|安全招聘|kanxue.com)
AsPack2.12分析及静态脱壳机的编写