打造快速关机迷你程序(改造PE文件---手搓)

本文介绍了一款利用VC实现的精简快速关机程序,通过优化代码和PE文件格式,实现了仅占用1.5KB的高效关机功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

晚上没什么事情做,正好又断网了,无聊就做了个迷你型的程序。

起初是想用纯手搓,C32结合OD来做,但是输入表那一块我想不起来了,又不能上网查,只好偷个懒,用VC先做个典型的小文件,然后我再去修改。

这个小东西只有一个功能,快速关机,相信很多朋友都知道XP系统的任务管理器,有一个关机的选项,按住Ctrl点关机,会马上关上。

与正常关机的区别就是:普通关机会结束所有进程,关闭所有窗口,保存所有数据,然后断电。快速关机就是不保存临时数据,执行必要关机流程之后断电。

所以,在我看来,只要是事先保存好了自己的所有数据后,采用快速关机的方法是可行的。

用VC来实现这个功能只需要一分钟,大家看了这个就明白了。

typedef enum _SHUTDOWN_ACTION
{
	ShutdownNoReboot,
	ShutdownReboot,
	ShutdownPowerOff
} SHUTDOWN_ACTION;
NTOSAPI NTSTATUS NTAPI NtShutdownSystem(IN SHUTDOWN_ACTION  Action);

这个函数被ntdll.dll导出了,所以直接拿来用即可。

但是我想把这个文件做到最小,这是VC所不能做到的,所以VC先做,我再做。

关于PE文件格式不懂的朋友可以先搜索一下,你就知道。

最小的PE文件是0x400字节,也就是1KB,PE头部(DOS头+NT头+区段信息)=0x200字节,区段=0x200字节。

这不能满足我的要求,还得用输入表,再加一个区段,所以最后我做出来的文件有0x600字节=1536字节=1.5KB。

可能有朋友会说,把代码段和输入表合并不就省下来一个区段了吗?结果证明0x200的空间写的代码确实不多,没那么多空间。

前言就那么多了,下面就开始干活:

新建个空Win32工程,代码如下

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "ntapi.h"
#pragma comment(linker, "/OPT:NOWIN98")

BOOL WINAPI DebugPrivilege(LPCTSTR PName)
{
	BOOL              bResult = TRUE;
	HANDLE            hToken;
	TOKEN_PRIVILEGES  TokenPrivileges;
	
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hToken))
	{
		bResult = FALSE;
		return bResult;
	}
	TokenPrivileges.PrivilegeCount = 1;
	TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	LookupPrivilegeValueW(NULL, PName, &TokenPrivileges.Privileges[0].Luid);
	AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
    if (GetLastError() != ERROR_SUCCESS)
	{
		bResult = FALSE;
	}
	CloseHandle(hToken);
	return bResult;	
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
	if (DebugPrivilege(NULL) == FALSE)
	{
		MessageBoxW(NULL, NULL, NULL, NULL);
	}
	else
	{
		if (MessageBoxW(NULL, NULL, NULL, MB_YESNO) == IDYES)
		{
			NtShutdownSystem(ShutdownPowerOff);
		}
	}
	return 0;
}


指定入口点,Release编译之后文件大小应该是2KB,距离目标很近了。

代码中没有使用字符串,因为用了之后文件还会增加一个区段,而这些字符串可以和代码段合并在一起。

现在与实现目标相差0x200字节,这个时候用C32打开,看到PE头部占用了0x400,多了0x200,而实际使用的数据只有0x200多一点点。

这就是MS的规定啊,必须要与0x200对齐,哪怕是0x201也得用0x400的空间。

浓缩一下,把DOS头精简,先清理DOS头的无用信息,然后移动NT头(网上叫PE头),修改PE头部大小数据,第一步OK。

现在这个文件物理偏移从0x200到0x400都是空白的了,括起来,DELETE,然后修改区段的偏移信息。

第一个区段,text,PointerToRawData数据原来是0x400,改成0x200,第二个区段rdata,原来是0x600,改成0x400,第二步OK。

保存,这个时候文件的大小就是1.5KB了,已经满足要求了。

接下来就是填入字符串数据,在代码段用OD写进去,再修正相应的PUSH指令即可。

现在,可以算是完工了,最小巧的实用型快速关机软件,哈哈。

------------------------------------------------------

我又继续做了些别的,把代码段全部NOP填充,重新自己写了反汇编代码,反正就俩函数,对比原来的反汇编和程序代码,好弄的很。

而且我发现自己写反汇编有点感觉了。

过程我就不说了,就是堆栈,内存,API,看的多了就好写了,直接上图。

感觉在效率上没啥变化,但是终归是自己一句一句写的,看着高兴。。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值