我在导入地址表中找到的所有导入为零的可移植可执行文件都不起作用。我也知道,虽然.NET经常文件不具有典型的OS进口,他们仍然必须进口要么_CorExeMain
或RHBinder__ShimExeMain
。
最后,即使是打包的文件,虽然它们没有主模块的导入,但仍然有启动和解压文件所必需的导入。.exe PE 文件是否有可能具有绝对零导入但仍然可以在机器上运行和执行任何有用的功能?
请注意:我不是在谈论其他可执行文件用于其函数导出的 DLL 文件。我说的是一个独立的 .exe 文件。
我在导入地址表中找到的所有导入为零的可移植可执行文件都不起作用。我也知道,虽然.NET经常文件不具有典型的OS进口,他们仍然必须进口要么_CorExeMain
或RHBinder__ShimExeMain
。
最后,即使是打包的文件,虽然它们没有主模块的导入,但仍然有启动和解压文件所必需的导入。.exe PE 文件是否有可能具有绝对零导入但仍然可以在机器上运行和执行任何有用的功能?
请注意:我不是在谈论其他可执行文件用于其函数导出的 DLL 文件。我说的是一个独立的 .exe 文件。
尽管 blabb 的回答显示了一个没有任何导入的可执行文件,但我假设 OP 是在询问功能更强大的可执行文件,而不是作为该级别的理论练习。
我可以想到四种合理的、可用的可执行文件类型,它们可能没有任何导入:
不需要任何操作系统 API 的可执行文件。
这有点类似于 blabb 的回答,但提出了一个更现实的例子。提出一个可以进行某种复杂计算的可执行文件可能就是一个例子。尽管如此,这似乎不是 OP 正在寻找的那种可执行文件。
通过使用默认加载的库来实现其功能的可执行文件。
不同的操作系统有不同的默认库,这可能并不总是可行的,但例如在 Windows 上ntdll.dll
并且kernel32.dll
总是加载到进程中,并且还可能加载其他库,具体取决于 PE 文件标志。其中一些甚至在处理大部分 PE 文件格式(特别是导入目录)之前由内核完成,其他库由加载器自动加载或由其他库依赖项加载。可执行文件可以在没有任何导入的情况下使用那些可用的 API,但是需要一些额外的工作来手动解析 API。
根据默认加载的库解析自己的导入的可执行文件。
使用前面提到的库中可用的 API,可执行文件可以实现自己的 API 搜索,甚至库加载代码,而无需实际导入所需的 API。这是一些包装工所做的。具体来说,那些GetProcAddr
在 Windows 上实现自己的功能,或者使用GetProcAddr
和LoadLibrary
动态加载带有空导入表的 API。
直接实现系统调用以使用操作系统服务的可执行文件。
这种可能性是最复杂和最脆弱的,因为直接实现系统调用很困难,并且可能会在没有事先警告的情况下在操作系统更新之间发生变化。基本上,大多数 API 以一条 syscall 指令结束,该指令将控制权转移到内核,在内核中,请求的操作实际上由内核执行。只要需要 OS 服务,可执行文件就可以直接发布这些文件。
void main (void)
{
__asm
{
retn
}
}
编译和链接使用
cl /nologo /W4 /Ox /analyze noimpo.cpp /link /DEBUG:NONE /RELEASE /ENTRY:main /INCREMENTAL:NO /FIXED /SUBSYSTEM:windows /ALIGN:128 /DRIVER
将创建一个工作 PE 文件
**编辑 **
// win 7 sp1 32 bit machine and ewdk 1703 cl.exe
unsigned long long time = 0xdeadbeefdeadbeef;
__declspec(naked) void main (void)
{
__asm
{
push OFFSET time
call ntqst
retn
}
ntqst:
__asm
{
mov eax,107h
mov edx , 7ffe0300h
call dword ptr ds:[edx]
retn 4
}
}
在调试器下运行,看看它是否真的做了一些有用的事情
cdb -c "g @$exentry;dq 400380 l1;pc;p;dq 400380 l1;.formats qwo(400380);.time;q" noimpo.exe | grep -i quit -B 16
00400380 deadbeef`deadbeef <----- marker
00400380 01d2ef24`40afa83a <----- actual result
Evaluate expression: < result from .formats
xxxxxxxxxxxxxxxxxxxxxxxxx
Time: Tue Jun 27 14:33:33.028 2017
xxxxxxxxxxxxxxxxxxxxxxxxx
result from .time command
Debug session time: Tue Jun 27 14:33:33.028 2017
xxx
quit:
是的,这是可能的,但可能取决于您尝试运行它的操作系统。来自Alexander Sotirov的TinyPE 页面:
不幸的是,97 字节的 PE 文件在 Windows 2000 上不起作用。这是因为加载程序试图从 KERNEL32 调用函数,但未加载 KERNEL32.DLL。所有其他版本的 Windows 都会自动加载它,但在 Windows 2000 上,我们必须确保 KERNEL32.DLL 列在可执行文件的导入表中。无法在没有导入的情况下执行 PE 文件。
因此,如果您使用 XP 或更高版本,则可以依靠 kernel32 在内存中并使用其功能。我怀疑(但没有检查)即使在 Windows 2000 上ntdll.dll
也是由内核映射的,因此您可以使用它来做有用的工作(例如LdrLoadDll
加载其他 DLL 和LdrGetProcedureAddress
解析函数)。