加壳程序初探,壳程序暂未写,加壳windows自带的软件不成功问题在哪?
本帖最后由 xiaoxiaoY520 于 2024-5-30 14:39 编辑最近看了加壳的一些文章,感觉加壳的原理和流程大概懂了,决定上手试一试,拿最简单的压缩壳上手,壳程序暂时未完成,加壳暂时也没用压缩算法,就简单的跟5A异或了一下,只是个初次上手的实验没想搞复杂。
写完了pe的结构并重组PE的逻辑,用的upx的结构(三节式的---空节、压缩数据节、shellcode节)。试了一下32位自己写的vs编译的没有问题,进了EntryOfPoint,但是在加64位程序和windows自带的计算器时,发现存在问题,加壳后加载不了,连设置的EntryOfPonit都到不了,查看结构是没有问题的,现在已经没辙了。代码和加完的64位计算器在附件。求助!求助!求助!
为了简便,我清除了datadirectory的结构,会不会是这个原因?亦或是windows自带组件有什么特别的验证机制在datadirectory里?现在只求能正常加载并进到EntryOfPoint链接:https://www.lanzouw.com/b00tam6mcd 密码:9bpp 附件密码:52pojie
你用 UPX 压缩一下系统软件就会看到“CantPackException: CFGuard enabled PE files are not supported (use --force to disable)”的提示
应该是微软的控制流防护(Control Flow Guard , CFG)保护了系统软件吧,你可以研究一下 UPX 源码
lies2014 发表于 2024-5-28 19:41
你用 UPX 压缩一下系统软件就会看到“CantPackException: CFGuard enabled PE files are not supported (us ...
应该不是这个原因,我已经把他关了仍然加载不进去,而且CFG保护的是代码执行流,我这是镜像加载失败,还没到CFG那一步吧,毕竟连oep都没到。
lies2014 发表于 2024-5-28 19:41
你用 UPX 压缩一下系统软件就会看到“CantPackException: CFGuard enabled PE files are not supported (us ...
x32dbg看了一下,入口点对的,断没断下来,ntdll.dll载入后就报错了,我看载入路径确实是32位的dll,但是不清楚为什么就挂了。DEP问题也排除了,已经关了DEP,节权限也改过无法断下。
用vs编译的自己写的hellword就没有问题,可以正常加载到入口点,而且写入32位的shellcode,用 peb去获取kernel32.dll也是成功的。
本帖最后由 爱飞的猫 于 2024-5-30 11:13 编辑
试着改了下,将 MajorSubsystemVersion 的值(文件偏移 `0x140`)降低到 6 后是会进入正常加载流程。
估计是 Win 10 的兼容层会检查额外的值,这个应该需要逆向 PE 文件加载流程了,不清楚怎么操作了。
试着跟了下 ntdll 的加载过程,`LdrpProcessMappedModule` 的这个分支,初始化 SecurityCookie 失败。
```cpp
if ( (a2 & 0x800000) == 0
&& ((*(_BYTE *)(a1 + 104) & 4) != 0 || a3 && (unsigned int)LdrpIsExecutableRelocatedImage(v3))
&& (*(_DWORD *)(a1 + 104) & 0x2000) == 0
&& a3 )
{
v14 = 0i64;
v10 = LdrpGenRandom();
inited = LdrInitSecurityCookie(v3, *(_DWORD *)(a1 + 64), 0, v10 ^ (unsigned int)dword_18019B3A8, (__int64)&v14);
if ( v3 == 0x180000000i64
|| !*(_QWORD *)(a1 + 56)
|| (*(_WORD *)(v13 + 72) != 6 || *(_WORD *)(v13 + 74) < 3u) && *(_WORD *)(v13 + 72) < 7u
|| inited )
{
Config = LdrpCfgProcessLoadConfig(a1, v13, v14);
if ( Config < 0 )
return (unsigned int)Config;
goto LABEL_18;
}
return 0xC000007B; // 此处失败
}
```
跟进去看,发现是在校验 Data Directory 的第 `0x0A` 项,该值不能为 0。
- `LdrInitSecurityCookie`
- `LdrpFetchAddressOfSecurityCookie`
- `LdrImageDirectoryEntryToLoadConfig(p_dos_hdr)`
- `RtlpImageDirectoryEntryToDataEx(pDosHeader, 1, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &v5, (__int64 *)&v6)`
- `if (nt_hdr->OptionalHeader.DataDirectory.VirtualAddress) { ... }`
```cpp
void **__fastcall LdrImageDirectoryEntryToLoadConfig(PIMAGE_DOS_HEADER pDosHeader)
{
NTSTATUS status; // eax
void **pEntryToConfig; // rdx
unsigned int v5; // BYREF
void **v6; // BYREF
PIMAGE_NT_HEADERS hdr; // BYREF
RtlImageNtHeaderEx(1i64, pDosHeader, 0i64, &hdr);
if ( !pDosHeader )
return 0i64;
status = RtlpImageDirectoryEntryToDataEx(pDosHeader, 1, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &v5, (__int64 *)&v6);
pEntryToConfig = v6;
if ( status < 0 )
pEntryToConfig = 0i64;
if ( pEntryToConfig && v5 && v5 == *(_DWORD *)pEntryToConfig && hdr->FileHeader.Machine == 0x8664 )
return pEntryToConfig;
else
return 0i64;
}
__int64 __fastcall RtlpImageDirectoryEntryToDataEx(
PIMAGE_DOS_HEADER a1,
char a2,
unsigned __int16 a3,
unsigned int *a4,
__int64 *a5)
{
// 省略片段
if ( nt_hdr->OptionalHeader.Magic == 0x20B && (unsigned int)idx < nt_hdr->OptionalHeader.NumberOfRvaAndSizes )
{
VirtualAddress = nt_hdr->OptionalHeader.DataDirectory.VirtualAddress;
if ( (_DWORD)VirtualAddress ) // 此处失败,因为该值被置 0
{
Size = nt_hdr->OptionalHeader.DataDirectory.Size;
LABEL_10:
*a4 = Size;
if ( v7 || (unsigned int)VirtualAddress < v12->OptionalHeader.SizeOfHeaders )
{
*a5 = v10 + VirtualAddress;
}
else
{
v15 = RtlAddressInSectionTable(v12, v10, (unsigned int)VirtualAddress);
*a5 = v15;
return v15 == 0 ? 0xC000000D : 0;
}
return v6;
}
return 0xC0000002;
}
// 省略片段
}
```
页:
[1]