首页
社区
课程
招聘
[原创][开源]用C++实现的壳(扩展版)
发表于: 2016-1-1 13:47 47512

[原创][开源]用C++实现的壳(扩展版)

2016-1-1 13:47
47512
收藏
免费 5
支持
分享
最新回复 (74)
雪    币: 77
活跃值: (1010)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
26
OK,那麻烦您了!贡献资料供大家学习!感谢感谢!
2016-1-3 18:51
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
27
对了,还需要一个PE文件编辑器,我这里选择的是PE Exolorer
2016-1-3 19:08
0
雪    币: 105
活跃值: (549)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
28
顶下学员。。。。
2016-1-3 21:29
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
29
楼主,你想破解的话,先准备工具,需要的工具ollydbg, PE Exolorer
Cheat Engine和VS2010,以及楼主的加壳程序!
先用VS2010建立一个控制台工程,
工程代码如下
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
        _asm int 3//这个代码一定需要,这个代码调用时会加载调试器,用来在不同调试器中使程序断在我想要的位置
        while(1)
        {
        while(::MessageBox(0,L"是否记录到导出表?",L"Test",MB_YESNO)==IDYES)
        {
                return 0;
        }
        }
        return 0;
}
然后打开工程设置,将工程设置为固定基地址,以及取消地址虚拟化,取消VC代码的折叠优化,不做以上设置,就会影响破解!
解释一下为什么要设置死循环,就是需要减少程序的启动次数!
好,将工程编译为Release版本,我们调试一下,没问题,正常调用!
用加密程序加密吧!加密时选择IAT加密,以及代码段加密,选择出现提示,以便我们附加需要的调试器,而程序中的INT 3指令,是帮助我们的调试器定位在我们的代码的,其余的我们都不

选,以免影响我们的破解!
//我们准备好已经加密过的程序以后,用PE Exolorer打开未加密的文件,查看一下导出表地址,我这里是00402224h 大小50h ,导出函数链表地址为00402000h 记录下来,备用
然后直接运行加密后的程序,如果加密无误,会弹出崩溃提示,这时我们附加VC的调试器上去,会看到VC弹出提示,遇到我们先前设置的断点!
断点后面的代码如下
00401003  int         3  //这里就是我们设置的断点,VC附加无误后会断在这里!
00401004  mov         eax,1  
00401009  test        eax,eax  
0040100B  je          0040102E  
0040100D  push        4  
0040100F  push        4020F4h  
00401014  push        402100h  
00401019  push        0  
0040101B  call        dword ptr ds:[4020A4h]//当运行到这里时,记录一下括号里面的值,我这里是4020A4h,然后找到导出表开始的地
记录值之后,停止VC调试,
打开Cheat Engine 61,然后运行加密过的程序,等弹出提示的时候,用CE附加它,然后选择手动添加指针,然后填入00402000
,添加指针之后,在指针列表上单击右键,选择找出是谁改写了这个指针,然后继续运行程序,之后CE会记录到,到底是什么地方改写了这个指针,也就是IAT的指针
接着打开CE的记录,单击第一个记录(一般是第一个的),然后点击 显示反汇编工具,就会自动找到改写这个IAT的地址,我这里是0040AFC8,
0040AFB0 - mov eax,[00407140] : [0041B000]
0040AFB5 - lea ecx,[esi+esi*4]
0040AFB8 - mov edx,[eax+ecx*4]
0040AFBB - mov eax,[004169C0] : [00260000]
0040AFC0 - mov ecx,[eax+esi*4]
0040AFC3 - mov eax,[004169D0] : [00400000]
0040AFC8 - mov [eax+edx],ecx
这时我们观察一下寄存器的值,

EAX=00400000
EBX=00270000
ECX=006B0000
EDX=00002000
ESI=0000000F
EDI=00000000
ESP=0018FF74
EBP=0018FF88
发现什么情况没有?
eax+edx=00402000 EAX就是模块基地址,那么EDX就是相对偏移 这么说这里的EDX保存的是原导入表地址啦?赶紧保存
什么情况00402000不是原导入表地址么?这里怎么进行了赋值操作?
ECX的值哪里来的?
mov ecx,[eax+esi*4]这里来的!
这句代码一看就知道类似 Addr[i]=值
那EAX的值就应该等于Addr的地址啦!
mov eax,[004169C0] : [00260000]
这里赋值EAX
看004169C0指向的地址,这像一个变量(经验判断的)
接着,在CE中添加地址,勾选指针类型,偏移量,我们写0
然后重启被加密的程序,然后附加CE,找到刚才添加的指针,右键,选择找出是谁访问了这个指针,弹出的对话框中选择第一个
然后,回到被加密程序中,单击确定,这时CE就记录了是谁访问了这个变量!
在弹出的代码列表中,选择第一个(一般都是第一个的)
然后按旁边的反汇编按钮,定位到改写这个变量的地址
我这里是0040B3BD
得到获取IAT地址的指令在那之后,
接下来就只能靠OD了,打开OD,用OD加载被加密程序之后,定位到0040B3BD
然后下断点,接下来,凭经验,找到填写这个地址的函数头,在那里下断点,
然后按F9运行,接着被加密程序会弹出消息框,我们单击确定,然后会陷入我们OD下的断点中,
接着,仔细了哦!别漏了,这里要有重要的事情发生了,仔细看寄存器,以及OD的显示
运行到0040b213处时,发生了什么事情?ECX寄存器里,居然得到了解密之后的模块文件名,

留一个题,你们自己分析,在上面已经运行过的代码中,可以分析出,加密的密钥是什么!
你们自己去分析吧!我就不去分析了直接修改代码,让解密以后,再进行加密混淆的代码无法运行!

模块文件名,我们得到了,接下来,继续运行
运行到0040B369处时候,我们得到了什么?居然是调用GetProceAddress哈哈,这就好办了,第一个参数是模块地址,第二个就是函数名!这就好办了,不用说,记录!
我们继续调试,当GetProceAddress返回时,居然看见了一个让我惊喜的东西,在0040B378处,看到了xor eax,15151515,哈哈,加密混淆指令,明显是使用GetProceAddress返回的地址与

15151515进行异或,当然不允许了,直接用NOP填充,接下来
函数调用了VirtualAlloc申请了内存,用来干嘛呢?接下来,有一大堆的指令,如果没有EAX寄存器的指令,我们直接忽略,接下来到了
0040B3A4 指令处,注意啊!注意看ECX的值,以及指令,
MOV DWORD PTR DS:[EDX*4+ECX],EAX这个指令很熟悉吧?不就是和前面赋值IAT的指令相似么?
再看看作为基地址的ECX的内容,ECX居然等于00260000,这不是前面的用于赋值给IAT的变量么?原来在这里,嘿嘿,不用说的,直接吧正确的地址给写回去,也就是GetProceAddress返回的

地址,写回去,把0040B396到0040B39F用NOP填充掉,把0040B36F到0040B388全部用NOP填充掉,下面,就是一些清除原导入表的操作,不用说的,果断NOP掉,别忘了保存一下函数与导入表的

关系,以及需要写入导出表的地址,否则,破解就白做了,
然后就用OD保存修改,
再用OD加载修改之后的程序,定位到OEP的最后的RET指令,这时在堆栈顶端,就可以看见原来的OEP,果断保存!
到此,我们得到了,模块名,函数名,以及对应的需要写入的IAT的地址:第一个IAT函数地址就是 00402000+0*4,第二个就是00402000+1*4,第三个就是00402000+2*4,以此类推,就能填写

IAT了,有了模块名,和函数名,自己写一个模块名与函数名的链表,然后就将IAT指向原IAT就行!

破解与获取IAT,以及获取OEP的方法,大家可以看看,哈哈有了原程序的IAT信息,我们自己构建IAT了,就不用麻烦楼主的壳给我恢复IAT了,也就直接过了你的老师的花指令!

好累啊!接下来的自己构建IAT的事,嘿嘿留给楼主自己了,看电脑久了,头大了!
2016-1-3 22:15
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
30
以上的破解做了之后,记录下之后,还要减去基地址0x0040000,才是正确的RVA,在下一次,调试时需要加上模块的基地址,才能得到真正的内存数据!别搞错,不要直接引用我的数据哦!我的数据只针对我的机器,不同机器的基地址是不同的,只有RVA是一样的哦!因此,得到相应的地址之后需要做计算的哦!
2016-1-3 22:20
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
31
我写错了,我改为

以上的破解做了之后,记录下之后,还要减去OEP所在节的基地址(我这里是0x00405000),才是正确的RVA,在下一次,调试时需要加上OEP所在节的基地址,才能得到真正的内存数据!别搞错,不要直接引用我的数据哦!我的数据只针对我的机器,不同机器的基地址是不同的,只有RVA是一样的哦!因此,得到相应的地址之后需要做计算的哦!

OEP所在节的基地址可以用PE Explorer,读取PE文件,查询到va,进而查询到rva,或者也可以使用debug相关的函数查询到RVA,相关知识可以去看PE文件结构了解
2016-1-3 22:32
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
32
我以上的破解方法,可以说是已知明文破解,也就是说,我知道解密后的程序,以及解密前的程序,然后调试解密的程序本身,通过对解密程序本身的调试,知道了它是如何工作的,以及工作需要的资源是存储在哪!然后,既然我知道了,加密程序的相关的资源在哪,以及是如何工作的,那么破解这个壳加密的别的程序,我就依样画葫芦,直接读取资源,然后破解就行了,这就是我的思路,说起来,这方法我是在红盟的教程里面学的,然而,这个教程里面却说,这种破解方法源自日本,是日本甲午战争的时候破解我国莫尔斯电码时用的方法!汗颜啊!
2016-1-3 22:41
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
33
建议楼主
OEP处先保存一下各个寄存器的值,备用!对IAT加密解密程序,代码进行加密,
然后申请一段内存,存入加密过的IAT,然后设置权限为无法读取,以及写入,然后注册一个异常回调函数,在准备进入原程序的OEP前,写一个有缓冲区溢出缺陷的函数,然后故意触发缓冲区溢出,在溢出的堆栈指向的地址中,我们写一个具有除0错误的汇编程序,然后这个汇编程序就修正堆栈,让其返回正常的函数,嘿嘿,这样除0错误,会被异常回调函数处理,异常回调函数会取得先前保存的OEP的各个寄存器的值,然后恢复寄存器,恢复寄存器后,我们就可以恢复IAT了,存入加密过的IAT的那段新的内存给予读取权限,然后恢复IAT,恢复以后,将模块名,全部指向一个系统存在,但是并没有加载的DLL,然后,将OEP地址恢复到EIP中,最后结束异常处理,然后卸载异常处理函数,当异常处理函数返回时,就跳到了原程序的OEP中了,而如果,在程序运行开始时有调试器试图附加,来调试你的IAT解密过程的话,由于调试器处理了缓冲区溢出,以及除0错误,所以不会导致异常处理代码的执行,那么IAT也就没有机会解密,这样就会导致程序无法完全解密了,同时破解难度也会提升的!
2016-1-4 00:13
0
雪    币: 77
活跃值: (1010)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
34
大牛,你这个对OEP的处理很棒的说!学习了学习了!!!
2016-1-4 00:52
0
雪    币: 41
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
35
从头开始学起。感谢分享!
2016-1-4 08:27
0
雪    币: 201
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
36
我先去看看基础版的,回头再来深入研究这个
2016-1-4 09:26
0
雪    币: 4938
活跃值: (977)
能力值: ( LV9,RANK:175 )
在线值:
发帖
回帖
粉丝
37
这个应该是加密壳类型的吧,根本就没压缩性...
选了代码段加密,然而代码段还是有一堆原指令出现,
iat加密比较简单,find #EB02FF15C3000000#几下就能修复了
StrongOD好久没更新了,bug也是有不少的
2016-1-4 10:01
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
38
这只是用来学习的,可以用来练手,不要纠结这么多
2016-1-4 18:54
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
39
楼主,刚刚写了一个隐藏OEP地址的壳代码的例子,要不要看一下?采用了异常处理链的方式调用了OEP,我想你如果想加强你的壳,你可以看一下嘿嘿,OEP中绝对不会出现原OEP地址,而且附带了部分的调试器检测功能!
2016-1-5 22:00
0
雪    币: 77
活跃值: (1010)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
40


我怕我真心看不懂了,我觉得我把这个壳的代码给你拓展,然后你再发个帖子普罗大众一下吧嘿嘿

我们现在开始学内核了,时间比较紧,壳我想就先放一放了...
2016-1-5 22:55
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
41
内核不好玩的,玩内核你小心了,给你个忠告,玩内核编程千万要注意,你得先准备几块硬盘!我玩内核编程时,报废了三块硬盘,以及一块显卡,BOSS被我弄坏了一次,系统嘛就不知道弄坏了多少次,嘿嘿,还是RING3好,绝对不会弄坏硬件!另外,你的壳我的VC 不支持,我还是贴出来吧!你自己能看懂多少就多少了,另外壳程序,我早就写过了,而且是半汇编的

代码如下// SetHardWare.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "SetHardWare.h"
typedef
ULONG
(NTAPI
*PRtlNtStatusToDosError)(
   ULONG Status
   );
//#include "../../testbase/Memory/Memory.h"
//PRtlNtStatusToDosError RtlNtStatusToDosError=(PRtlNtStatusToDosError)::GetProcAddress(::GetModuleHandle(L"Ntdll.dll"),"RtlNtStatusToDosError");
#include "../../BPHookFunction/BPHookFunction/BPHookFunction.h"
//#include "../../testbase/Memory/Memory.h"
#define MAX_LOADSTRING 100
typedef ULONG (WINAPI *pfnRtlDispatchException)(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);
pfnRtlDispatchException m_fnRtlDispatchException=(pfnRtlDispatchException)::GetProcAddress(::GetModuleHandleA("ntdll"),"KiUserExceptionDispatcher");;
// 全局变量:
HINSTANCE hInst;                                                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                                        // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];                        // 主窗口类名
int APIENTRY _tWinMain2(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow);
// 此代码模块中包含的函数的前向声明:
ATOM                                MyRegisterClass(HINSTANCE hInstance);
BOOL                                InitInstance(HINSTANCE, int);
LRESULT CALLBACK        WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK        About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain2(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow);
LONG WINAPI MyTopUnhandledExceptionFilter(
         struct _EXCEPTION_POINTERS *ExceptionInfo
);
                //  extern "C" __declspec(dllimport) ULONG NTAPI  RtlNtStatusToDosError(
//  _In_ LONG Status
//);
BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext)
{
  // 返回TRUE,这个异常我已经处理好了,继续运行程序
  // 返回FALSE,这个异常不是我的,找别人处理去
        MessageBox(0,L"DDDD",L"DDSADS",0);
        return 1;
}
ULONG WINAPI _RtlDispatchException( PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext )
{
  if(RtlDispatchException(pExcptRec,pContext)) return 1;
  return m_fnRtlDispatchException(pExcptRec,pContext);
}
BOOL HookSystemSEH()
{
        m_fnRtlDispatchException=(pfnRtlDispatchException)::GetProcAddress(::GetModuleHandleA("ntdll"),"KiUserExceptionDispatcher");
        return 0;
//        return SetInlineHook((PVOID*)&m_fnRtlDispatchException,_RtlDispatchException);
}
DWORD Address = 0,EndAddress = 0;
LPVOID Data = 0;
DWORD IsCall = 0;
HANDLE VectoredHandler = 0;
VOID WINAPI RegFilter()
{
        PVOID Data = (PVOID)Address;
        if(RtlNtStatusToDosError==0) exit(0);
#ifndef _DEBUG
        if(::IsDebuggerPresent()) return ;
#else

#endif
        VectoredHandler=AddVectoredExceptionHandler(1,MyTopUnhandledExceptionFilter);
        if(VectoredHandler==0) exit(0);
}
int WINAPI Show()
{
        return ::MessageBox(0,L"我差,居然有调试器,请结束调试器!",L"调试器",16);
}
__declspec(naked)int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
        _asm
        {
                mov edi,edi//WINAPI 约定调用方式 这里的一大堆指令,其实就是一个意思,就是jmp _tWinMain2
                push ebp
                        mov ebp, esp
         push eax
         lea eax,dword ptr[Error]
         mov Address,eax
         lea eax,dword ptr[End]
         mov EndAddress,eax
         mov eax,110
         xor ebx ,ebx
         pop eax
        mov esp,ebp
                pop ebp                               
                 mov eax,110
        push eax
                        push dword ptr[Next]
                push RegFilter
                ret
       
Next:                pop eax
        Error:        _asm idiv ebx
                        call Show
                        ret 16
End:
               
                #ifdef _DEBUG
                ret 16
        #else
                call dword ptr[DebugBreak]
                push Error+2
                #endif
                ret
                        ret 16
        }
}
LONG WINAPI MyTopUnhandledExceptionFilter(
         struct _EXCEPTION_POINTERS *ExceptionInfo
)
                 {
                         PVECTORED_EXCEPTION_HANDLER Handler=(PVECTORED_EXCEPTION_HANDLER)VectoredHandler;
                //         return Handler(ExceptionInfo);
                         WCHAR Buffer[32]={0};
                        DWORD  ExceptionCode=RtlNtStatusToDosError(ExceptionInfo->ExceptionRecord->ExceptionCode);
                //        ExceptionCode=::BaseNtStatusToDosError(ExceptionCode);
                        //_asm int 3 c0000094
                        //wsprintf(Buffer,L"%x",ExceptionCode);
                        //MessageBox(0,Buffer,L"Text",0);
                        //if(IsCall==1)
                        if(IsCall==2) return 0;
                        if(ExceptionInfo->ExceptionRecord->ExceptionCode==0x80000003)
                        {
                                if(ExceptionInfo->ContextRecord->Eax==120)
                                //if(EndAddress==(DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress)
                                {
                                                        ExceptionInfo->ContextRecord->Eax=119;
                                                        ExceptionInfo->ContextRecord->Esp=ExceptionInfo->ContextRecord->Esp+4;
                                                        ExceptionInfo->ContextRecord->Eip=(DWORD)Data;
                                                        return EXCEPTION_CONTINUE_EXECUTION;
                                }
                                return 0;
                        }
                        if(ExceptionCode==998)
                        {
                                //if(ExceptionInfo->ExceptionRecord->ExceptionAddress==(PVOID)Data)
                        //        {
                        //if(IsCall==2) return 0;

                        if(ExceptionInfo->ExceptionRecord->ExceptionAddress==Data)
                        {
                                memset(Data,0,16);
                                VirtualFree(Data,16,MEM_DECOMMIT);
                                        if(ExceptionInfo->ContextRecord->Eax==119)
                                        {
                                                IsCall=2;
                                                ExceptionInfo->ContextRecord->Eip=(DWORD)_tWinMain2;
                                                return EXCEPTION_CONTINUE_EXECUTION;
                                        }
                        }
                        //        }
                        }
                        if(ExceptionInfo->ExceptionRecord->ExceptionCode==0xc0000094)
                        {
                                //ExceptionInfo->ExceptionRecord->
                                if(ExceptionInfo->ExceptionRecord->ExceptionAddress==(PVOID)Address)
                                {
                                        if(ExceptionInfo->ContextRecord->Eax==110)
                                        {
                                                 Data=VirtualAlloc(0,16,MEM_COMMIT, PAGE_READWRITE);
                                                 //::IsDebuggerPresent()
                                                 BOOL IsDebug= ::IsDebuggerPresent();
                                                #ifndef _DEBUG
                           //  if(::IsDebuggerPresent()) return ;
                          #else
                                                 IsDebug=FALSE;
                           #endif
                                                 if(IsDebug)
                                                 {
                                                         #ifndef _DEBUG
                                                ExceptionInfo->ContextRecord->Eip=ExceptionInfo->ContextRecord->Eip+2;
                                                #else
                                                         ExceptionInfo->ContextRecord->Eip=(DWORD)_tWinMain2;
                                                         #endif
                                                //return EXCEPTION_CONTINUE_EXECUTION;
                                                         RemoveVectoredExceptionHandler(VectoredHandler);
                                                        return EXCEPTION_CONTINUE_EXECUTION;
                                                 }
                                                 #ifdef _DEBUG
                                                 ExceptionInfo->ContextRecord->Eip=(DWORD)_tWinMain2;
                                                 RemoveVectoredExceptionHandler(VectoredHandler);
                                                 return EXCEPTION_CONTINUE_EXECUTION;
                                                 #endif
                                                if(Data==0)
                                                {
                                                        //exit(0);
                                                        ExceptionInfo->ContextRecord->Eip=ExceptionInfo->ContextRecord->Eip+2;
                                                }else
                                                {
                                                        CONTEXT lpContext={0};
                                                        IsCall=1;
                                                        memset(Data,0xcc,16);
                                                        ExceptionInfo->ContextRecord->Eax=120;
                                                        ExceptionInfo->ContextRecord->Eip=EndAddress;
                                                }
                                        }
                                }
                                return EXCEPTION_CONTINUE_EXECUTION;
                        }
                         return 0;
                 }
int APIENTRY _tWinMain2(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);

        // TODO: 在此放置代码。
//        _asm int  3
        MSG msg;
        HACCEL hAccelTable;

        // 初始化全局字符串
        LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadString(hInstance, IDC_SETHARDWARE, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
       
        // 执行应用程序初始化:
        if (!InitInstance (hInstance, nCmdShow))
        {
                return FALSE;
        }

        hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SETHARDWARE));

        // 主消息循环:
        while (GetMessage(&msg, NULL, 0, 0))
        {
                if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
                {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                }
        }

        return (int) msg.wParam;
}

//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
//  注释:
//
//    仅当希望
//    此代码与添加到 Windows 95 中的“RegisterClassEx”
//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
//    这样应用程序就可以获得关联的
//    “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
        WNDCLASSEX wcex;

        wcex.cbSize = sizeof(WNDCLASSEX);

        wcex.style                        = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc        = WndProc;
        wcex.cbClsExtra                = 0;
        wcex.cbWndExtra                = 0;
        wcex.hInstance                = hInstance;
        wcex.hIcon                        = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SETHARDWARE));
        wcex.hCursor                = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground        = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName        = MAKEINTRESOURCE(IDC_SETHARDWARE);
        wcex.lpszClassName        = szWindowClass;
        wcex.hIconSm                = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

        return RegisterClassEx(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // 将实例句柄存储在全局变量中

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND        - 处理应用程序菜单
//  WM_PAINT        - 绘制主窗口
//  WM_DESTROY        - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        int wmId, wmEvent;
        PAINTSTRUCT ps;
        HDC hdc;

        switch (message)
        {
        case WM_COMMAND:
                wmId    = LOWORD(wParam);
                wmEvent = HIWORD(wParam);
                // 分析菜单选择:
                switch (wmId)
                {
                case IDM_ABOUT:
                        DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                        break;
                case IDM_EXIT:
                        DestroyWindow(hWnd);
                        break;
                default:
                        return DefWindowProc(hWnd, message, wParam, lParam);
                }
                break;
        case WM_PAINT:
                hdc = BeginPaint(hWnd, &ps);
                // TODO: 在此添加任意绘图代码...
                EndPaint(hWnd, &ps);
                break;
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
                return (INT_PTR)TRUE;

        case WM_COMMAND:
                if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
                {
                        EndDialog(hDlg, LOWORD(wParam));
                        return (INT_PTR)TRUE;
                }
                break;
        }
        return (INT_PTR)FALSE;
}

实际入口点为_tWinMain2,VC,为我们连接的入口点是_tWinMain,至于为什么入口点是_tWinMain,因为这是一个例子,不用更改mainCRTStartup的,这里做演示就已经够了!
2016-1-5 23:38
0
雪    币: 77
活跃值: (1010)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
42
ok!这个我收藏了

十分感谢大神的赐教!

我还处在学习阶段,勉励!
2016-1-6 07:56
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
43
这个 真是不错
2016-1-8 09:04
0
雪    币: 986
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
44
学习了,支持楼主
2016-1-8 16:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
45
这个版块是不是大牛最多的,怎么发现了N多精华和关注,研究壳的都是大牛啊。膜拜
2016-1-11 15:19
0
雪    币: 27
活跃值: (27)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
46
太高深了,看不懂,我小菜一个写的程序没人感兴趣unpack
2016-1-12 18:17
0
雪    币: 151
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
47
楼主写的不错,支持一下
2016-1-14 08:34
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
48
楼主大神啊,这个神器能脱阿里加固吗?
2016-1-15 14:22
0
雪    币: 1
活跃值: (111)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
49
多谢楼主分享
2016-2-3 14:52
0
雪    币: 51
活跃值: (30)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
50
我擦,居然有调试器
2016-3-3 14:20
0
游客
登录 | 注册 方可回帖
返回
//