分享
 
 
 

利用资源文件实现对软件的保护

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

前一段时间在设计项目的软件时,出于对软件保护的考虑,想把主程序和其所需的支持库隐藏起来。经过一番讨论和思考,决定另做一个程序作为外壳程序,以资源文件的形式把主程序文件和支持库加载到外壳程序里,在外壳程序运行时实现对主程序和其所需支持库的自动释放和删除。这样不仅实现了对软件的保护,而且在程序发布时只需给用户一个可执行文件(外壳程序),用户使用和管理起来也就更方便。下面以Windows自带程序write.exe(主程序)为例说明具体的实现方法。

一、资源文件的建立和使用

打开纯文本编辑软件(如notepad),按照格式

资源名 资源类型 资源的文件名

输入以下内容:

ding WAV ding.wav

1stboot BITMAP 1stboot.bmp

write EXE c:\write.exe

保存为资源文件mysrc.rc。这样就生成了一个资源文件。需要注意的是,如果路径中含有中文,那么要将文件名放在双引号里面。

启动C++ Builder,打开新工程,将资源文件mysrc.rc添加进项目中。你也可以通过BIN目录下的

brcc32.exe将RC文件编绎为RES文件,然后用 #program resource "*.res" 语句将其联编进项目中。我们采用更简单的前一种方法。编译运行后外壳程序里就含有了主程序和其所需的支持库。

二、资源的释放及调用

因为我们用的资源是可执行文件和支持库,所以不能只在内存中操作,要释放成文件。其他诸如声音、位图等资源只要在内存中操作既可,这里就不再赘述了。把资源释放成文件的方法也非常简单。下面给出源代码:

void __fastcall TForm1::ReleaseExefile()

{

//TODO: Add your source code here

HRSRC hMyRes;

HGLOBAL hgpt;

LPVOID lpBuff;

DWORD rcSize=20480; //20480为write.exe的大小

HANDLE hFile;

LPDWORD dwByte;

dwByte=&rcSize;

hMyRes=FindResource(HInstance,"write","exe");

//HInstance指示资源所在地为执行文件

if(hMyRes==NULL)

ShowMessage(SysErrorMessage(GetLastError()));

hgpt=LoadResource(NULL,hMyRes);

if(hgpt==NULL)

ShowMessage(SysErrorMessage(GetLastError()));

lpBuff=LockResource(hgpt);

//写入文件

try

{

hFile=CreateFile("e:\\mywrite.exe",GENERIC_WRITE,0,NULL, CREATE _ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

WriteFile(hFile,lpBuff,rcSize,dwByte,NULL);

if(*dwByte!=20480)

ShowMessage("无法写入文件!");

}

__finally

{

CloseHandle(hFile);

}

}

这样就在硬盘的E盘根目录下生成了一个mywrite.exe文件,在外壳程序中调用它既可。

Windows为在程序中调用其它程序提供了许多API函数如已经过时的LoadModule()、为16位Windows程序兼容性设立的WinExec()和基于32位Windows程序的CreateProcess()、ShellExecute()/ShellExecuteEx()。

ShellExcute()只有6个参数,使用起来要简单得多。函数的声明如下:

HISTANCE ShellExecute (

HWND hwnd, //父窗体句柄

LPCTSTR lpOperation, //指向文件处理方式字符串的指针

LPCTSTR lpFile, //指向文件名字符串的指针

LPCTSTR lpParameters, //指向可执行文件运行参数字符串的指针

LPCTSTR lpDirectory, //指向默认路径字符串的指针

INT nShowCmd //标志程序被显示的方式

);例如:

if(FileExists("e:\\mywrite.exe"))

{

ShellExecute(NULL,"Open","e:\\mywrite.exe",NULL,NULL,SW_SHOWNORMAL);

}

三、自动删除文件及消息的使用

在用户点击关闭后,我们要删除硬盘上的主程序文件。但由于管理权限不够,不能让主程序删除自身,所以还要借助外壳程序来实现。这样的话就用到了Windows的消息机制。

消息(Message)指的就是Windows操作系统发给应用程序的一个通告,它告诉应用程序某个特定的事件发生了。从数据结构的角度来说消息是一个结构体,结构如下:

typedef struct

{

HWND hwnd; //检索消息的窗口句柄

UINT message; //代表一个消息的消息质

WPARAM wParam; //消息附加信息的字参数

LPARAM lParam; //消息附加信息的长字参数

DWORD time; //消息入队时间

POINT pt; //消息发送时鼠标的位置point.x,point.y

}tagMSG

Windows操作系统中的消息从其发生到被处理完成一般有5个步骤:

(1)系统发生了一个事件

(2)Windows系统把事件翻译为对应的消息并把它放到消息队列中。

(3)应用程序从消息队列中获取消息,然后把它封装在TMSG结构中。

(4)应用程序通过消息循环分派给对应的窗口函数。

(5)窗口函数最终处理这个消息。

应用程序也可以像Windows系统一样在窗口或者是组件之间发消息。C++ Builder为此提供了几种途径:使用函数TControl::Perform()或者API函数SendMessage()和PostMessage()向特定窗体发送消息,或者是使用函数TWinControl::Broadcast()和API函数

BroadcastSystemMessage()广播消息。

我们采用了使用API函数PostMessage()向特定窗体发送消息 WM_CLOSE的方法。PostMessage()的原型声明如下:

Bool PostMessage(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM lParam);

例如:PostMessage(Handle,WM_CLOSE,0,0); //Handle为接收消息的窗体(外壳程序)句柄。

主程序关闭后向外壳程序发送一个关闭消息,外壳程序接收到主程序发送的WM_CLOSE消息后,响应关闭事件,我们就可以在外壳程序的FormClose事件中实现文件的动态删除。

四、隐藏程序

这种保护方法的关键是不能显示出有两个应用程序在运行,所以应该将外壳程序隐藏起来。这要考虑窗体、任务栏图标和CTRL-ALT-DEL对话框等方面。

1、隐藏窗体和任务栏图标

想隐藏窗体要将窗体的Visible属性设为false,想隐藏程序的任务栏图标可以用ShowWindow函数并传给它窗口句柄 ShowWindow(Application->Handle,SW_HIDE);但通过ShowWindow函数来隐藏窗口的任务栏图标图标是不持久的。某些动作会使任务栏图标重现。可以将隐藏的应用程序窗口设为Tool Window来移走程序的任务栏图标而避免它再次出现。Tool Window永远不会有任务栏图标。但把应用程序窗口设为Tool Window有一个副作用:当用户按下Alt+Tab时它会出现在程序列表中。可以调用API函数GetWindowLong()和SetWindowLong()来使应用程序窗口成为一个Tool Window,源代码如下:

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

{

DWORD dwExStyle=GetWindowLong(Application->Handle,GWL_EXSTYLE);

dwExStyle|=WS_EX_TOOLWINDOW;

SetWindowLong(Application->Handle,GWL_EXSTYLE,dwExStyle);

try

{

Application->Initialize();

Application->Title = "动态释放";

Application->CreateForm(__classid(TForm1), &Form1);

Application->ShowMainForm=false;

Application->Run();

}

catch (Exception &exception)

{

Application->ShowException(&exception);

}

return 0;

}

这样就隐藏了程序的任务栏图标,但它还会显示在CTRL-ALT-DEL对话框中。

2、不显示在CTRL-ALT-DEL对话框中

最常用的方法是调用RegisterServiceProcess API 函数将程序注册成为一个服务模式程序。 RegisterServiceProcess是一个在Kernel32.dll里相关但无正式文件的函数。这个函数的主要目的是创建一个服务模式程序。但由于windows NT下没有RegisterServiceProcess函数。所以这种方法只能在Windows95/98下实现。源代码如下:

//------------Header file------------------------------

typedef DWORD (__stdcall *pRegFunction)(DWORD, DWORD);

class TForm1 : public TForm

{

__published:

TButton *Button1;

private:

HINSTANCE hKernelLib;

pRegFunction RegisterServiceProcess;

public:

__fastcall TForm1(TComponent* Owner);

__fastcall ~TForm1();

};

//-----------CPP file------------------------------

#include "Unit1.h"

#define RSP_SIMPLE_SERVICE 1

#define RSP_UNREGISTER_SERVICE 0

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

hKernelLib = LoadLibrary("kernel32.dll");

if(hKernelLib)

{

RegisterServiceProcess =(pRegFunction)GetProcAddress(hKernelLib,"RegisterServiceProcess");

if(RegisterServiceProcess)

RegisterServiceProcess(GetCurrentProcessId(),RSP_SIMPLE_SERVICE);

}

}

__fastcall TForm1::~TForm1()

{

if(hKernelLib)

{

if(RegisterServiceProcess)

RegisterServiceProcess(GetCurrentProcessId(),RSP_UNREGISTER_SERVICE);

FreeLibrary(hKernelLib);

}

}

经过这样处理后我们就在系统中看不见外壳程序的身影,从而给人一种只有一个程序(主程序)的错觉。

在WinNT下只要我们的程序是以进程内核的形式运行,都不可能逃离CTRL+ALT+DEL的法眼。当然也有瞒天过海的方法,但在这里不适用,故不再赘述。

结束语

这种把主程序作为资源文件使用并在外壳程序运行过程中动态生成和删除主程序的方法只是提供了一种软件保护的思路,并不能从根本上解决问题。但如果把主程序和外壳程序用不同的加壳软件(如AsPack,Upx等)加壳,会使程序的破解变得更加困难。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有