首页
社区
课程
招聘
[原创]滴水逆向学习收获1-双进程无dll注入(1楼,17楼,21楼,27楼,30楼,33楼)[已更新至33楼]
发表于: 2011-11-8 17:30 49018

[原创]滴水逆向学习收获1-双进程无dll注入(1楼,17楼,21楼,27楼,30楼,33楼)[已更新至33楼]

2011-11-8 17:30
49018
收藏
免费 7
支持
分享
最新回复 (48)
雪    币: 277
活跃值: (209)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
26
不好意思,让你们久等了。。。
2011-12-5 18:43
0
雪    币: 277
活跃值: (209)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
27
滴水学习收获1-双进程无dll注入详解(三)

目录:
1.      程序效果演示
2.      注入程序的注入原理
3.      程序的数据结构<本节>
4.      程序的初始化<下节>
5.   <待定>

上一篇我们了解了双进程通信的原理和机制,从现在开始我们将进入代码看看具体的实现过程。
开始我们先了解一下程序的数据结构。
主要数据结构:
typedef struct  
{
        HANDLE InEvent;
        HANDLE OutEvent;
        BYTE *MapViewpBuff;
} IoEvnet_t;
存放程序通信的事件名和FileMap缓冲区地址

typedef struct
{
        int (__stdcall *MessageBoxA)(HWND hWnd ,        LPCSTR lpText,LPCSTR lpCaption,UINT uType);
        char m_chNtdll[sizeof("ntdll.dll")];
} EgLowAPIAddr_t;
存放copy到被注入程序函数要用的API地址和数据

typedef struct  
{
        ULONG Fun;
        ULONG InLength;
        ULONG OutLength;
        ULONG OutLengthReal;
        ULONG *InBuffer;
        ULONG *OutBuffer;
       
        EgLowAPIAddr_t EgLowAPIAddr;
       
       
        ULONG PipeInBuffer[0x1000/4];
        ULONG PipeOutBuffer[0x20000/4];
        ULONG PipeFunCodeBuffer[CodeLength/4];
       
} MapFile_t;
// 存放拷贝到被注入程序里的函数和函数执行要用到的数据

typedef struct
{
        int ok;
        char Text[0x80];
        char Caption[0x80];

        DWORD CopyFunOffset[0x20];

        char EVENT_NAMEUI[sizeof(UIDATA_EVENT_NAMEUI)];
        char EVENT_NAMEEG[sizeof(UIDATA_EVENT_NAMEEG)];
        char FILEMAP_NAME[sizeof(UIDATA_FILEMAP_NAME)];

        char Tip[sizeof("Tip")];
        char OpenIoEvnetError[sizeof("Open IoEvnet Error")];
        char OpenFileMapError[sizeof("OpenFileMap Erro")];
        char MapViewOfFileError[sizeof("MapViewOfFile Error")];
        //--------------------------------------------

        int (__stdcall *MessageBoxA)(HWND hWnd ,        LPCSTR lpText,LPCSTR lpCaption,UINT uType);

        HANDLE (__stdcall *OpenEventA)(DWORD dwDesiredAccess,BOOL bInheritHandle,char *lpName);
        HANDLE (__stdcall *OpenFileMappingA)(DWORD dwDesiredAccess,BOOL bInheritHandle,char *lpName);
        LPVOID (__stdcall *MapViewOfFile)(HANDLE hFileMappingObject,DWORD dwDesiredAccess,DWORD dwFileOffsetHigh,DWORD dwFileOffsetLow,DWORD dwNumberOfBytesToMap);
        DWORD (__stdcall *WaitForSingleObject)(HANDLE hHandle,DWORD dwMilliseconds);
        BOOL (__stdcall *SetEvent)(HANDLE hEvent);
        VOID (__stdcall *Sleep)(DWORD dwMilliseconds);

#define CODEBUFFERSZIE        0x2000

        BYTE CodeBuffer[CODEBUFFERSZIE];
       
} ThreadParam_t;
//拷贝到被注入程序的函数和执行函数要用到的API和数据。

主要的全局变量:
IoEvnet_t IoEvnet;                // 存放进程通信的事件名和FileMap缓冲区地址
MapFile_t *MapFilep;        // 记录存放被拷贝函数的信息缓冲区的首地址,该缓冲区在FileMap缓冲区中,在此记下地址是为了方便使用。

<本节代码见21楼>
2011-12-5 18:44
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
28
好贴子,谢谢楼主的分享
2011-12-5 19:12
0
雪    币: 57
活跃值: (68)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
29
无dll 注入,标记一下,会用的找
2011-12-9 18:49
0
雪    币: 277
活跃值: (209)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
30
目录:
1.程序效果演示
2.注入程序的注入原理
3.程序的数据结构
4.程序的初始化<本节>
5.程序的注入过程<下节>
6.待定
前面几篇都在做准备工作,没有真正进入程序的流程。现在开始我们看看程序从准备注入到运行的整个过程。本篇讲程序在注入前要做的工作,即初始化工作。
程序的初始化在注入进程的InitEGWork函数中完成。
该函数如下:
BOOL InitEGWork()
{
        //
        m_hEvent_UI = NULL;
        m_hEvent_EG = NULL;
        hMapFile = NULL;
        pBuf = NULL;
       
        m_hEvent_UI = CreateEvent(NULL, 0, 0, UIDATA_EVENT_NAMEUI);
        m_hEvent_EG = CreateEvent(NULL, 0, 0, UIDATA_EVENT_NAMEEG);
       
        InitializeCriticalSection(&EventIoCriticalSection);
       
       
        // MapFile
        hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,0x60000,UIDATA_FILEMAP_NAME);
        if (hMapFile==NULL || hMapFile==INVALID_HANDLE_VALUE)
        {
                AfxMessageBox("CreateFileMapping Error");
                return FALSE;
        }
       
        pBuf = (LPSTR)MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,MAPFILESIZE);
       
        IoEvnet.InEvent = m_hEvent_UI;
        IoEvnet.OutEvent = m_hEvent_EG;
        IoEvnet.MapViewpBuff = MAPFILEOFFSET+(unsigned char*)pBuf;
       
        MapFilep = (MapFile_t *)(IoEvnet.MapViewpBuff+8);
       
        *(DWORD*)&MapFilep->EgLowAPIAddr.MessageBoxA =
                (DWORD)GetProcAddress(GetModuleHandle("USER32.dll"),"MessageBoxA");
       
        strcpy(MapFilep->EgLowAPIAddr.m_chNtdll,"ntdll.dll");
       
        return TRUE;
}
代码分析:
1>
m_hEvent_UI = CreateEvent(NULL, 0, 0, UIDATA_EVENT_NAMEUI);
m_hEvent_EG = CreateEvent(NULL, 0, 0, UIDATA_EVENT_NAMEEG);
分别创建了双进程通信要用到的两个事件对象。最后一个参数UIDATA_EVENT_NAMEUI和UIDATA_EVENT_NAMEEG是事件名,注入后被注入进程打开事件也要用到这两个事件名。
2>        hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,0x60000,UIDATA_FILEMAP_NAME);
        if (hMapFile==NULL || hMapFile==INVALID_HANDLE_VALUE)
        {
                AfxMessageBox("CreateFileMapping Error");
                return FALSE;
        }
创建FileMap内核对象,并检测是否创建成功,不成功则提示创建发失败!
3>pBuf = (LPSTR)MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,MAPFILESIZE);
得到创建的FileMap缓冲区地址
4>
        IoEvnet.InEvent = m_hEvent_UI;
        IoEvnet.OutEvent = m_hEvent_EG;
        IoEvnet.MapViewpBuff = MAPFILEOFFSET+(unsigned char*)pBuf;
得到与被注入程序通信所需的事件句柄和缓冲区地址
5>
MapFilep = (MapFile_t *)(IoEvnet.MapViewpBuff+8);
*(DWORD*)&MapFilep->EgLowAPIAddr.MessageBoxA =
                (DWORD)GetProcAddress(GetModuleHandle("USER32.dll"),"MessageBoxA");
strcpy(MapFilep->EgLowAPIAddr.m_chNtdll,"ntdll.dll");
此段代码的功能是保存被注入代码运行所需的函数地址和数据。

本篇代码见21楼
2011-12-14 17:23
0
雪    币: 63
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
31
楼主辛苦!!!
2011-12-26 11:25
0
雪    币: 271
活跃值: (196)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
32
先收藏一个,有时间再看
2011-12-26 18:15
0
雪    币: 277
活跃值: (209)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
33
滴水学习收获1-双进程无dll注入详解(五)
目录:
1.程序效果演示
2.注入程序的注入原理
3.程序的数据结构
4.程序的初始化
5.程序的注入过程<本节>
6.远程线程函数<下节>
7.待定
在“注入”按钮对应的函数里调用InitEGWork()函数完成初始化工作后,调用了如下代码
CreateThread(NULL,NULL,CreateRemoteThreadProc,NULL,0,0);
创建了一个线程,该线程完成向被注入进程注入代码。线程函数是
DWORD WINAPI  CreateRemoteThreadProc(void* lp)
我们跟进去可以看到注入代码实现是在函数
DWORD CreateRemoteThreadProc(char *processname,char *processname2)
中。该函数是我们今天的重点。先来看看这个函数的代码。
DWORD CreateRemoteThreadProc(char *processname,char *processname2)
{
        DWORD prcessID;
        HANDLE  hProcess;
        HMODULE uu;

        DWORD OffsetRemoteThread;
        DWORD CopyFunOffset[0x20];
        DWORD CopyFunLength[0x20];

        int i;
        ThreadParam_t *ThreadParamp;
        //-----------------------------------------------------------------------------------
        //-----------------------------------------------------------------------------------
        //-----------------------------------------------------------------------------------
       

        prcessID = 0;
        hProcess = NULL;
        uu = 0;
        ThreadParamp = (ThreadParam_t *)LocalBuffer;

        strcpy(ThreadParamp->Text,"注入成功!");
        strcpy(ThreadParamp->Caption,"提示");

        strcpy(ThreadParamp->EVENT_NAMEUI,UIDATA_EVENT_NAMEUI);
        strcpy(ThreadParamp->EVENT_NAMEEG,UIDATA_EVENT_NAMEEG);
        strcpy(ThreadParamp->FILEMAP_NAME,UIDATA_FILEMAP_NAME);
        strcpy(ThreadParamp->Tip,"tip");
        strcpy(ThreadParamp->OpenIoEvnetError,"Open IoEvnet Error");
        strcpy(ThreadParamp->OpenFileMapError,"OpenFileMap Erro");
        strcpy(ThreadParamp->MapViewOfFileError,"MapViewOfFile Error");

        *(DWORD*)&ThreadParamp->MessageBoxA = (DWORD)GetProcAddress(GetModuleHandle("USER32.dll"),"MessageBoxA");
        *(DWORD*)&ThreadParamp->OpenEventA = (DWORD)GetProcAddress(GetModuleHandle("KERNEL32.dll"),"OpenEventA");
        *(DWORD*)&ThreadParamp->OpenFileMappingA = (DWORD)GetProcAddress(GetModuleHandle("KERNEL32.dll"),"OpenFileMappingA");
        *(DWORD*)&ThreadParamp->MapViewOfFile = (DWORD)GetProcAddress(GetModuleHandle("KERNEL32.dll"),"MapViewOfFile");
        *(DWORD*)&ThreadParamp->WaitForSingleObject = (DWORD)GetProcAddress(GetModuleHandle("KERNEL32.dll"),"WaitForSingleObject");
        *(DWORD*)&ThreadParamp->SetEvent = (DWORD)GetProcAddress(GetModuleHandle("KERNEL32.dll"),"SetEvent");
        *(DWORD*)&ThreadParamp->Sleep = (DWORD)GetProcAddress(GetModuleHandle("KERNEL32.dll"),"Sleep");

        void *RemoteFunList[] =
        {
                &RemoteThread,
                NULL
        };
       
        CopyFunctions(RemoteFunList,CopyFunOffset,CopyFunLength,ThreadParamp->CodeBuffer,CODEBUFFERSZIE);
        for (i=0;RemoteFunList[i];i++)
        {
                if (RemoteFunList[i]==(void*)RemoteThread)
                {
                        OffsetRemoteThread = CopyFunOffset[i];
                        break;
                }
        }
        //memcpy(ThreadParamp->CopyFunOffset,ThreadParamp,4*0x20);
        //-----------------------------------------------------------------------------------
        //-----------------------------------------------------------------------------------
        //-----------------------------------------------------------------------------------
       
        for(;;)
        {
                Sleep(3);
                prcessID = GetProcessId(processname,processname2);
               
                if(prcessID && (PatchFlag == 0))
                {
                        EnableDebugPriv();
       
                        hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,prcessID);
                        if(hProcess == NULL)
                        {
                                DWORD eroor = GetLastError();
                                MessageBox(NULL,"open process error!!!",NULL,MB_OK);
                        }

                        WritedThread(hProcess,OffsetRemoteThread);
                        CloseHandle( hProcess );
                        PatchFlag = 1;
                       
                        break;
                }
        }
        return 1;
}

我们是用远程线程注入的,在讲解代码前先说说远程线程注入的大致过程.远程线程注入先要将线程函数和线程函数要用到的函数和数据拷贝到被注入的进程中,然后创建远程线程执行线程函数。
1>在本程序中远程线程函数和函数要用到的数据都存放在变量ThreadParamp所指向的内存中。
void *RemoteFunList[] =
        {
                &RemoteThread,
                NULL
        };
是要拷贝的函数列表。该表以上代码是将远程要用的字符串和API地址保存在ThreadParamp指向内存的对应位置。
2> CopyFunctions(RemoteFunList,CopyFunOffset,CopyFunLength,ThreadParamp->CodeBuffer,CODEBUFFERSZIE);
将1中列出的函数考贝到ThreadParamp指向的内存的CodeBuffer缓冲区中
3>
        for (i=0;RemoteFunList[i];i++)
        {
                if (RemoteFunList[i]==(void*)RemoteThread)
                {
                        OffsetRemoteThread = CopyFunOffset[i];
                        break;
                }
        }
得到远程线程在CodeBuffer中的偏移
4>prcessID = GetProcessId(processname,processname2);
得到被注入进程的ID
5>EnableDebugPriv();
调整自身权限是可以操作被注入进程
6>hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,prcessID);
得到被注入进程句柄
7>WritedThread(hProcess,OffsetRemoteThread);
将远程线程代码和数据(ThreadParamp所指向的内存)写入到被注入进程中,被创建远程线程执行线程函数
2012-1-5 17:01
0
雪    币: 296
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
34
good job.
2012-1-8 12:04
0
雪    币: 602
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
35
收藏 无dll双进程注入
2012-1-8 13:12
0
雪    币: 199
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
36
话说这跟dll有什么区别。。。
2012-1-10 17:15
0
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
37
顶下来学习下...
2012-1-13 09:17
0
雪    币: 45
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
38
什么原理啊..
2012-1-13 12:54
0
雪    币: 123
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
39
不错,站位学习
2012-1-13 15:20
0
雪    币: 261
活跃值: (1802)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
40
360 拦截了 不好用
2012-1-16 11:39
0
雪    币: 227
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
41
有没有简化版的。。这个构架太复杂。。。能简单通讯就行
2012-1-19 19:08
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
42
360拦了,苦恼!
2012-1-31 11:54
0
雪    币: 1644
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
43
学习。。。。
2012-2-8 10:45
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
44
好东东,学习了!!!!
2012-3-10 09:06
0
雪    币: 237
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
45
看不懂,不过顶一个。
2012-3-23 18:39
0
雪    币: 50
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
46
楼主的进步真是在飞呀,感谢楼主分享
2012-4-2 13:12
0
雪    币: 615
活跃值: (212)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
47
看上去很不错.......
2012-4-2 13:46
0
雪    币: 224
活跃值: (157)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
48
谢谢分享,非常感谢!
2012-4-2 15:51
0
雪    币: 1486
活跃值: (1135)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
49
大神,编译错误        5        error  C2011:  “_PROCESS_INFORMATION_CLASS”:“enum”类型重定义,WIN7系统VS2013编译
2017-10-26 16:05
0
游客
登录 | 注册 方可回帖
返回