首页
社区
课程
招聘
[原创]几种常用的保护应用程序的方法,编写成类库
发表于: 2008-6-25 15:31 11144

[原创]几种常用的保护应用程序的方法,编写成类库

2008-6-25 15:31
11144

几种常用的保护应用程序的方法 ( 作者:老实和尚  coverlove@163.com )

1、前言
        目前很多程序员都没有软件安全的意识,对自己辛辛苦苦的劳动成果不加保护,而这些缺乏保护意识的程序在日益强大的SoftIce, OllyDBG(OllyICE), W32DASM等工具面前显得如此脆弱,一个稍微有点经验的Cracker可能在几分钟之内就可以轻易的突破防线;有些程序员虽然有了保护自己程序的意识,但是一般都完全依赖于专业的保护软件进行加壳保护,对自己的程序本身在编码阶段却完全不设防,而这些知名的壳也并非安全,目前对这些知名的壳都有专门的脱壳工具和脱壳教材,一旦这些壳被剥掉,那么呈现在Cracker面前的也完全是一些赤裸裸的代码。
        本文主要介绍在软件编码阶段进行一些必要的保护手段,在编译生成二进制代码后再进行外部加壳保护处理,这样应该更安全一些,一旦壳被攻破,还有内部的保护机制在起作用,已经写成类库,觉得有用的可以下载稍微修改即可使用。

2、常用的几种编码阶段的保护手段

A、检测SoftIce驱动是否安装

检测SoffIce的驱动是否存在来判断是否安装了SoftIce,代码如下:

if(CreateFile( "\\\\.\\NTICE", GENERIC_READ | GENERIC_WRITE,
              FILE_SHARE_READ | FILE_SHARE_WRITE,
              NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
              NULL)!=INVALID_HANDLE_VALUE)
        {
            There is SoftICE NT on your system;
        }
if(CreateFile( "\\\\.\\SICE", GENERIC_READ | GENERIC_WRITE,
              FILE_SHARE_READ | FILE_SHARE_WRITE,
              NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
              NULL)!=INVALID_HANDLE_VALUE)
        {
            There is SoftICE98 on your system;
        }

B. 程序窗口句柄检测
       
检测是否存在窗口Ollyice或者OllyDbg等等,读者可以自行添加

char name1[]="OLLYDBG";

char name2[]="OLLYICE";

HWND hwnd=BlurFindWindow(name1); //循环检测windows所有顶层窗口,只要窗口名称中含有(模糊匹配)字符串name1,name2的窗口则说明存在Ollyice或者OllyDbg

if(hwnd!=NULL)
{
        There is OLLYDBG on your system;
}
hwnd=BlurFindWindow(name2);

if(hwnd!=NULL)
{
        There is OLLYICE on your system;
}

C. 用线程环境块检测

TEB(Thread Environment Block) 在 Windows 9x 系列中被称为 TIB(Thread Information Block),它记录了线程的重要信息,而且每一个线程都会对应一个 TEB 结构。在TEB结构的 30h 偏移处存放着另外一个重要的数据结构的首地址PPEB:
typedef struct _NT_TEB
{
NT_TIB Tib; // 00h
PVOID EnvironmentPointer; // 1Ch
CLIENT_ID Cid; // 20h
PVOID ActiveRpcInfo; // 28h
PVOID ThreadLocalStoragePointer; // 2Ch
PPEB Peb; // 30h
ULONG LastErrorValue; // 34h
ULONG CountOfOwnedCriticalSections; // 38h
PVOID CsrClientThread; // 3Ch
PVOID Win32ThreadInfo; // 40h
ULONG Win32ClientInfo[0x1F]; // 44h
PVOID WOW32Reserved; // C0h
ULONG CurrentLocale; // C4h
ULONG FpSoftwareStatusRegister; // C8h
PVOID SystemReserved1[0x36]; // CCh
PVOID Spare1; // 1A4h
LONG ExceptionCode; // 1A8h
ULONG SpareBytes1[0x28]; // 1ACh
PVOID SystemReserved2[0xA]; // 1D4h
GDI_TEB_BATCH GdiTebBatch; // 1FCh
ULONG gdiRgn; // 6DCh
ULONG gdiPen; // 6E0h
ULONG gdiBrush; // 6E4h
CLIENT_ID RealClientId; // 6E8h
PVOID GdiCachedProcessHandle; // 6F0h
ULONG GdiClientPID; // 6F4h
ULONG GdiClientTID; // 6F8h
PVOID GdiThreadLocaleInfo; // 6FCh
PVOID UserReserved[5]; // 700h
PVOID glDispatchTable[0x118]; // 714h
ULONG glReserved1[0x1A]; // B74h
PVOID glReserved2; // BDCh
PVOID glSectionInfo; // BE0h
PVOID glSection; // BE4h
PVOID glTable; // BE8h
PVOID glCurrentRC; // BECh
PVOID glContext; // BF0h
NTSTATUS LastStatusValue; // BF4h
UNICODE_STRING StaticUnicodeString; // BF8h
WCHAR StaticUnicodeBuffer[0x105]; // C00h
PVOID DeallocationStack; // E0Ch
PVOID TlsSlots[0x40]; // E10h
LIST_ENTRY TlsLinks; // F10h
PVOID Vdm; // F18h
PVOID ReservedForNtRpc; // F1Ch
PVOID DbgSsReserved[0x2]; // F20h
ULONG HardErrorDisabled; // F28h
PVOID Instrumentation[0x10]; // F2Ch
PVOID WinSockData; // F6Ch
ULONG GdiBatchCount; // F70h
ULONG Spare2; // F74h
ULONG Spare3; // F78h
ULONG Spare4; // F7Ch
PVOID ReservedForOle; // F80h
ULONG WaitingOnLoaderLock; // F84h

PVOID StackCommit; // F88h
PVOID StackCommitMax; // F8Ch
PVOID StackReserve; // F90h

PVOID MessageQueue; // ???
} NT_TEB, *PNT_TEB;

PPEB  Peb;       // 30h Pointer to owning process database

这个偏移地址处的内容非常有用,它指向本线程的拥有者的 PEB(Process Database) 的线性地址。这个结构的02h 偏移处存放着进程是否被调试的标志。当有调试器调试进程时这个BeingDebugged会被置1,否则为0,可以通过这个标志来检测是否被调试器调试。

typedef struct _PEB
{
                        UCHAR InheritedAddressSpace;                     // 00h
                        UCHAR ReadImageFileExecOptions;                  // 01h
                        UCHAR BeingDebugged;                             // 02h
                        UCHAR Spare;                                     // 03h
                        PVOID Mutant;                                    // 04h
                        PVOID ImageBaseAddress;                          // 08h
                        PPEB_LDR_DATA Ldr;                               // 0Ch
                        PRTL_USER_PROCESS_PARAMETERS ProcessParameters;  // 10h
                        PVOID SubSystemData;                             // 14h
                        PVOID ProcessHeap;                               // 18h
                        PVOID FastPebLock;                               // 1Ch
                        PPEBLOCKROUTINE FastPebLockRoutine;              // 20h
                        PPEBLOCKROUTINE FastPebUnlockRoutine;            // 24h
                        ULONG EnvironmentUpdateCount;                    // 28h
                        PVOID* KernelCallbackTable;                      // 2Ch
                        PVOID EventLogSection;                           // 30h
                        PVOID EventLog;                                  // 34h
                        PPEB_FREE_BLOCK FreeList;                        // 38h
                        ULONG TlsExpansionCounter;                       // 3Ch
                        PVOID TlsBitmap;                                 // 40h
                        ULONG TlsBitmapBits[0x2];                        // 44h
                        PVOID ReadOnlySharedMemoryBase;                  // 4Ch
                        PVOID ReadOnlySharedMemoryHeap;                  // 50h
                        PVOID* ReadOnlyStaticServerData;                 // 54h
                        PVOID AnsiCodePageData;                          // 58h
                        PVOID OemCodePageData;                           // 5Ch
                        PVOID UnicodeCaseTableData;                      // 60h
                        ULONG NumberOfProcessors;                        // 64h
                        ULONG NtGlobalFlag;                              // 68h
                        UCHAR Spare2[0x4];                               // 6Ch
                        LARGE_INTEGER CriticalSectionTimeout;            // 70h
                        ULONG HeapSegmentReserve;                        // 78h
                        ULONG HeapSegmentCommit;                         // 7Ch
                        ULONG HeapDeCommitTotalFreeThreshold;            // 80h
                        ULONG HeapDeCommitFreeBlockThreshold;            // 84h
                        ULONG NumberOfHeaps;                             // 88h
                        ULONG MaximumNumberOfHeaps;                      // 8Ch
                        PVOID** ProcessHeaps;                            // 90h
                        PVOID GdiSharedHandleTable;                      // 94h
                        PVOID ProcessStarterHelper;                      // 98h
                        PVOID GdiDCAttributeList;                        // 9Ch
                        PVOID LoaderLock;                                // A0h
                        ULONG OSMajorVersion;                            // A4h
                        ULONG OSMinorVersion;                            // A8h
                        ULONG OSBuildNumber;                             // ACh
                        ULONG OSPlatformId;                              // B0h
                        ULONG ImageSubSystem;                            // B4h
                        ULONG ImageSubSystemMajorVersion;                // B8h
                        ULONG ImageSubSystemMinorVersion;                // C0h
                        ULONG GdiHandleBuffer[0x22];                     // C4h

                        PVOID ProcessWindowStation;                     
} PEB, *PPEB;
代码如下:
int exist=0;
__asm
        {
                pushad
                //在fs:[0x18]再加上0x30就是指向了TEB结构
                mov   eax,fs:[0x18]     //pTeb 线性地址
        mov   eax, dword ptr  [eax+0x30]    //pPeb的首地址
                //获取PEB偏移2h处BeingDebugged的值       
                movzx eax,byte ptr[eax+0x02]
                or al,al       
                jz No
                jnz Yes
           No:
                 mov exist,0
                 jmp Exit
           Yes:
                 mov exist,1

                 jmp Exit
           Exit:          
                popad
        }       
        if(exist)
        {
                // The process is debugged

        }

D、用API函数IsDebuggerPresent检测

if(IsDebuggerPresent())
{
        // The process is debugged

}

E、利用异常SEH机制

利用异常检测调试器,下面这段代码执行throw(&exce)
的时候会抛出异常,然后进入到我们设置好的异常处理例程将bIsInDebugger设置为FALSE,而一旦调试器运行这段代码的时候,异常首先被调试器截获,如果调试器截获后进行了处理而没有继续传递给我们的异常处理例程,那么将不会执行bIsInDebugger=FALSE从而达到检测调试器的目的。

BOOL bIsInDebugger = TRUE ;

CFileException exce;

try
{
           // 抛出异常
               
                throw(&exce);

                //throw(1);

}
catch(int )
{
        bIsInDebugger = TRUE ;

}
catch(CFileException *)
{
       
        bIsInDebugger = FALSE ;
}

       
if( bIsInDebugger )
{
        // The process is debugged

}

F、使用自己的函数替代部分系统函数,完成同样的功能

        比如:替换上面的IsDebuggerPresent函数,拷贝IsDebuggerPresent函数的实现代码为自己所用,这样可以避免Cracker使用bpx IsDebuggerPresent断点来跟踪我们的程序。偷系统的代码实现如下:



(系统API IsDebuggerPresent实现的二进制代码 )

__declspec( naked )  BOOL CDebugProtect::IsDebuggerPresentEx()
{
        __asm
        {
                mov     eax, dword ptr fs:[18h]
                mov     eax, dword ptr [eax+30h]
                movzx   eax, byte ptr [eax+2h]
                retn
        }
}
这样在调用IsDebuggerPresent的地方都可以用IsDebuggerPresentEx替换掉。当然有些函数只能替换高层API,对于底层API还是无法替换的,这样Cracker可以在更底层的API上面下断点,再跟踪到调用的地方。

G、使用动态获取DLL函数地址替代使用隐式调用DLL
隐式调用DLL中函数的地方,很容易让Crack通过引用API参考找到下断点的地方,Cracker只需要简单的双击引用API地址的行就能定位到调用API的地方。

DWORD CDebugProtect::TerminateFun=GetProcAddr("kernel32.dll","TerminateProcess");

DWORD CDebugProtect::GetProcAddr(const char *dll,const char *fun)
{
        //const char * pszModName = "kernel32.dll";

        //const char * pszTerminatelName = "TerminateProcess";

        const char * pszModName=dll;

        const char * pszTerminatelName =fun;

        HMODULE hKernel = GetModuleHandle(pszModName);
       
        FARPROC proc=GetProcAddress(hKernel,pszTerminatelName);

        return (DWORD)proc;

}

如在类的静态变量中获取TerminateProcess函数的地址,然后在调用TerminateProcess的地方使用这个变量来终止进程,这样Cracker就不能简单的下断点bpx TerminateProcess。

如下:在类的静态变量初始化时候完成API地址的获取,在实际使用的时候使用这个地址直接CALL,下面是两个API地址隐藏的实现方法。

DWORD apiAddr=TerminateFun; // TerminateFun是一个静态变量,在类第一次使用前已经被初始化

HANDLE currentp=GetCurrentProcess(); //当前进程句柄

  _asm
{
                        pushad

                        push 0
                       
                        push currentp

                        call apiAddr //形成的汇编代码就很难通过函数参考来找到

                        popad

}

//获取硬盘ID,通过隐藏API地址调用
DWORD   GenerateID(void)
{
        const char * lpRootPathName="c:\\";   //取C盘的序列号

        char lpVolumeNameBuffer[12];  //磁盘卷标

        unsigned long int nVolumeNameSize=12;
       
        unsigned long int VolumeSerialNumber;  //磁盘序列号
        unsigned long int MaximumComponentLength;
        char  lpFileSystemNameBuffer[10];
        unsigned long int nFileSystemNameSize=10;
        unsigned long int FileSystemFlags;

        DWORD apiAddr=GetVolumeInformationFun;

        __asm
        {
                pushad  

                push nFileSystemNameSize

                lea eax, lpFileSystemNameBuffer
               
                push eax

                lea eax, FileSystemFlags  

                push eax

                lea eax, MaximumComponentLength

                push eax

                lea eax, VolumeSerialNumber

                push eax

                push nVolumeNameSize

                lea eax, lpVolumeNameBuffer
               
                push eax

                push lpRootPathName //常量字符串变量本身就代表地址,直接使用即可不再使用lea

                call apiAddr

                popad

        }

//原来的调用方式

//        GetVolumeInformation(lpRootPathName,
//                lpVolumeNameBuffer, nVolumeNameSize,
//                &VolumeSerialNumber, &MaximumComponentLength,
//                &FileSystemFlags,
//                lpFileSystemNameBuffer, nFileSystemNameSize);

        VolumeSerialNumber^=0x12345678;

        return  VolumeSerialNumber;  //给用户显示机器码使用,硬盘伪序列号
       
}

H、 检查程序的父进程是否为EXPLORER.EXE
一个正常的EXE文件应该是由EXPLORER.EXE来加载的,所以其父进程应该是EXPLORER.EXE,可以通过这个检测点来检测是否被调试。

char lpszSystemInfo[MAX_PATH];
HANDLE hSnapshot=NULL;

        DWORD PID_child;
        DWORD PID_parent,PID_explorer;
        HANDLE hh_parnet = NULL;
    PROCESSENTRY32        pe32 = {0};
        pe32.dwSize = sizeof(PROCESSENTRY32);//0x128;
    PID_child=GetCurrentProcessId();//getpid();
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
        if (Process32First(hSnapshot, &pe32))
    {
                while (Process32Next(hSnapshot, &pe32))
                {
                        GetFileNameFromPath(pe32.szExeFile);
            CharUpperBuff(pe32.szExeFile,strlen(pe32.szExeFile));
            if(strcmp(pe32.szExeFile,"EXPLORER.EXE")==0)
            {
                PID_explorer=pe32.th32ProcessID;
            }
                        if(pe32.th32ProcessID==PID_child)
                        {
                                PID_parent=pe32.th32ParentProcessID;
                        }
                }
        }
    if(PID_parent!=PID_explorer)
    {
        hh_parnet= OpenProcess(PROCESS_ALL_ACCESS, TRUE, PID_parent);
                res=TRUE;       
        //TerminateProcess(hh_parnet, 0);

           _asm
           {
                        pushad
                        push 0               
                        push hh_parnet
                        call apiAddr
                        popad
           }
    }
        else
        {
                MODULEENTRY32        me32 = {0};
                me32.dwSize = sizeof(MODULEENTRY32);
                hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,PID_explorer);
                if (Module32First(hSnapshot, &me32))
                {
                    do
            {
                            if(PID_explorer==me32.th32ProcessID)
                            {
                                        GetWindowsDirectory(lpszSystemInfo, MAX_PATH+1);
                                        strcat(lpszSystemInfo,"\\");
                                        strcat(lpszSystemInfo,"EXPLORER.EXE");
                                        CharUpperBuff(me32.szExePath,strlen(me32.szExePath));
                                        if(strncmp(me32.szExePath,lpszSystemInfo,strlen(lpszSystemInfo)))
                                        {
                                                GetFileNameFromPath(me32.szExePath);
                                                if(strcmp(me32.szExePath,"EXPLORER.EXE")==0)
                                                {
                                                        hh_parnet= OpenProcess(PROCESS_ALL_ACCESS, TRUE, PID_explorer);
                                                        res=TRUE;
                                                        //TerminateProcess(hh_parnet, 0);
                                                          _asm
                                                           {
                                                                        pushad
                                                                        push 0                       
                                                                        push hh_parnet
                                                                        call apiAddr
                                                                        popad
                                                           }
                                                }
                                        }
                }
            }while (Module32Next(hSnapshot, &me32));
                }
        }

I、检查STARTUPINFO结构
Windows操作系统中的explorer.exe创建进程的时候会把STARTUPINFO结构中的值设为0,而非explorer.exe创建进程的时候会忽略这个结构中的值,也就是结构中的值不为0,所以可以利用这个来判断是否在调试程序
STARTUPINFO Info;
//通过检测STARTUPINFO结构来检测debugger
GetStartupInfo(&Info);
   if ( (Info.dwX != 0) || (Info.dwY !=0) || (Info.dwXCountChars != 0) || (Info.dwYCountChars !=0 ) || (Info.dwFillAttribute != 0) || (Info.dwXSize != 0) || (Info.dwYSize != 0) )
   {
         //TerminateProcess(GetCurrentProcess(), 0);
            _asm
           {
                        pushad
                        push 0       
                        push currentp
                        call apiAddr
                        popad
           }
   }

J、 所有的检测函数返回值只作为参考,而更多的返回值可以通过unsigned char * output来判断

        在主程序中判断函数调用是否成功,可以通过返回值EAX来作初步判断,更准确的判断可以通过复杂的数据结构output来判断,而output的值在函数正常执行完成后进行填充,防止Cracker直接修改函数的返回值EAX来暴力破解。

K、敏感的字符串都进行异或或者可逆变换处理,再使用的地方动态解密出来
        对于敏感的字符串信息需要进行简单的加密处理,否则Cracker可以通过简单的字符串参考就能找到敏感信息的代码地址,在引用字符串的地方先解密再使用,也不要弹出对话框等暴露敏感字符串信息。
L、对文件进行代码段的CRC校验处理
        可以对内存中的PE文件的进行一些CRC校验处理而不要对文件系统中的文件进行CRC校验,因为访问文件本身就是CRC破解的一个突破口。由于编译后我们的二进制代码又进行了加壳等外部处理,整个PE文件的结构发生了重大变化,进行CRC校验已经非常困难,所以此种方法对加壳的PE文件处理比较麻烦。
M、使用花指令等方法防止静态分析
W32Dasm等工具反编译出来的汇编指令如果没有花指令干扰,反编译出来的结果非常容易让Cracker分析,因此可以故意设置一些花指令“陷阱”,让W32Dasm落入我们设下的“陷阱”了。花指令的实质是利用了反编译工具没有人脑那么智能的,它们往往会把人为加入的一些指令理解错,从而错误地确定了指令的起始位置,导致分析错误,而实质上加入花指令后并没有改变原来的程序执行流程,从而达到干扰目的。更详细的介绍请参看罗聪的博客:
(http://www.luocong.com/articles/show_article.asp?Article_ID=14)
3、基于以上几种手段的编写的一个类


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 228
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
沙发,太高兴了!哈哈哈
2008-6-25 16:09
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
多谢,很有启发
2008-6-25 16:43
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
太厉害了
2008-6-25 20:12
0
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
5
多数方法在《加密与解密》都有了。
2008-6-26 00:58
0
雪    币: 2362
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
顶!!!
很有用··谁叫我买不起书
2008-6-26 06:45
0
雪    币: 133
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
总结一下就是好。顶
2008-6-26 09:47
0
雪    币: 322
活跃值: (56)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
8
为了防止这个类库将VC IDE也当作调试经常杀死,可以加#ifndef  _DEBUG宏,参考如下:尽量分散多个地方多调用几次:)

#ifndef  _DEBUG

        unsigned char output[100];

        BOOL resutl=FALSE;

        resutl=CDebugProtect::AntiDebug(output,100);

        if(resutl) return FALSE;

        //BOOL res=CDebugProtect::Ollydbg(output,10);

        srand( (unsigned)time( NULL ) );

        int index= rand() % 99 ; //rand() 0 -0x7fff

        if(output[index]!=index+1)  //随机检查返回缓冲区,用户可以自己定义,防止eax爆破
        {
                return FALSE;
        }
       
        resutl=CDebugProtect::Ollydbg(output,100);

        if(resutl) return FALSE;

        srand( (unsigned)time( NULL ) );

        index= rand() % 99 ; //rand() 0 -0x7fff

        if(output[index]!=index+1)
        {
                return FALSE;
        }

        resutl=CDebugProtect::SoftIceDeteck(output,100);

        if(resutl) return FALSE;

        srand( (unsigned)time( NULL ) );

        index= rand() % 99 ; //rand() 0 -0x7fff

        if(output[index]!=index+1)
        {
                return FALSE;
        }

#endif
2008-6-27 15:11
0
雪    币: 2316
活跃值: (129)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
9
很强大,学习下。
2008-6-27 16:44
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不错,最近非常需要用到。有几种方法还是很有借鉴意义的。
2008-7-1 09:43
0
雪    币: 82
活跃值: (10)
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
11
希望可以继续完善
2008-7-1 09:46
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
好久不见精华文章了,支持一下...
2008-7-1 12:51
0
雪    币: 411
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
谢谢!精华文章。
2008-7-1 13:25
0
雪    币: 277
活跃值: (2126)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
14
谢谢楼主分享,是个好东西
2008-7-1 13:30
0
雪    币: 561
活跃值: (124)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
谢谢分享
2008-7-1 14:43
0
雪    币: 202
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
2008-7-2 08:49
0
雪    币: 322
活跃值: (56)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
17
希望坛子里有更高能力的人添加更多的方法,我到时候整合成类,供大家下载使用
2008-7-2 18:11
0
雪    币: 2316
活跃值: (129)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
18
内容是不太丰富。楼主提到的方法,OD的应可全部通过。
IsdebugPresent,checkStartupinfo,无论是API还是自己代码,hideod修改几个标志就可通过了。
parentprocess,Hideod处理了Process32NextW,也可通过。
异常,只要设置OD忽略所有异常,也可通过。
推荐peter pierre的<unpacker tirck>里面的方法很全。
2008-7-2 21:47
0
雪    币: 52
活跃值: (2082)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
最好能有DELPHI的
2008-7-2 21:59
0
雪    币: 322
活跃值: (56)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
20
都是类的静态函数,很容易移植到DELPHI,希望收集到更多的方法,满足一般性要求
2008-7-4 16:59
0
游客
登录 | 注册 方可回帖
返回
//