首页
社区
课程
招聘
[旧帖] [邀请码已发][原创]inline hook + WriteProcessMemory 注入DLL 0.00雪花
发表于: 2011-6-14 18:35 2433

[旧帖] [邀请码已发][原创]inline hook + WriteProcessMemory 注入DLL 0.00雪花

2011-6-14 18:35
2433
(本文实现 windows核心编程 里面没有实现的 Dll注入)
1. 让进程生成一个被挂起的子进程
2. 从.exe模块的文件头中取得主线程起始内存地址
3. 将位于该内存地址处的机器指令保存起来
4. 强制将一些手工编写的机器指令写入到该内存地址.这些指令调用LoadLibrary装载一个Dll
5. 恢复子进程运行,让这些指令得到执行
6. 把保存起来的指令恢复到起始处
7. 让进程从起始地址继续执行,就好像什么都没有发生过一样
   汗!打了这么多子累死了

(注意了,这里用的方法要比书上说的好一些.  书上说只能是子进程才行! 本文的办法不是子进程照样能注入)

// 代码大致说明

1. 修理shellcode
2. 创建进程(打开其它进程,暂停其运行也行)
3. 写入shellcode到进程, 挂住线程将要执行的位置(不管是什么指令都可以挂钩,因为后shelcodel恢复钩子),
        保存挂钩处代码(为5个字节)到shellcode
        (下面的代码只是勾住入口点)
4. 释放线程

        //
        //
        //shellcode 执行 流程
        //

        //加载 你要注入的Dll
        IAT->_LoadLibraryA((LPCSTR)_relocal(inject_dllname));

        // 把堆栈中的返回点减5 (通过 堆栈参数 &argc -1 就是 ret 指令返回点的EIP)
        unsigned long *entry_esp = (unsigned long *)&argc;
        entry_esp --;
        // EIP 减 5 (就能返回到原来才行执行的位置了)
        *entry_esp -= 5;
       
        // 恢复挂钩处得代码
        void *pentry = (void *)(*entry_esp);
        void *entry_c = (void *)_relocal(original_entry);
        IAT->_WriteProcessMemory(
                IAT->_GetCurrentProcess(), pentry, entry_c, 5, NULL);

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
//==========================================================================
// shellcode 部分代码
// 具体编写参考 yuange 2001年的c语言直接直接生成  shellcode, 你用汇编也行
//===============================================================================
 
 
 
// manal jmp to main()
char jmp_main[] = "\xE9\0\0\0\0";
 
char original_entry[] = "original_entry";
char inject_dllname[0x100] = "inject_dllname";
 
char loadlibrary_str[] = "LoadLibraryA";
 
 
int main(int argc, char* argv[])
{
    _IMPORT_AT *IAT = (_IMPORT_AT *)_relocal(&g_IAT);
 
    // Initialize import address table by loadlibraryA
    InitializeIAT(_GetLoadLibraryA());
     
    IAT->_LoadLibraryA((LPCSTR)_relocal(inject_dllname));
     
    // sub return point, 5
    unsigned long *entry_esp = (unsigned long *)&argc;
    entry_esp --;
    *entry_esp -= 5;
 
    // revert hooked entry point code
    void *pentry = (void *)(*entry_esp);
    void *entry_c = (void *)_relocal(original_entry);
    IAT->_WriteProcessMemory(
        IAT->_GetCurrentProcess(), pentry, entry_c, 5, NULL);
 
    return 0;
}
 
 
//==========================================================================
//
// 注入完整代码
//
//=======================================================================
 
CWinApp theApp;
 
using namespace std;
 
UCHAR *_FixShellcode(LPCSTR lpszInjectFileName, ULONG *pEntry, LPCSTR lpszShellFileName, ULONG *pSize)
{
    //
    // lpszInjectFileName
    //
    HMODULE hModule = LoadLibraryEx(
        lpszInjectFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);
    ASSERT(hModule);
 
    unsigned char *Image = (unsigned char *)hModule;
     
    PIMAGE_DOS_HEADER pimg_dos_h = (PIMAGE_DOS_HEADER)Image;
    PIMAGE_NT_HEADERS pimg_nt_h = (PIMAGE_NT_HEADERS)
        (Image+pimg_dos_h->e_lfanew);
     
    ULONG AddressOfEntryPoint = pimg_nt_h->OptionalHeader.ImageBase +
        pimg_nt_h->OptionalHeader.AddressOfEntryPoint;
 
    char entrycode[5];
    memcpy(entrycode, (Image+pimg_nt_h->OptionalHeader.AddressOfEntryPoint), 5);
 
    /// 汗! 调试的 时候居然会崩溃   在 ntdll
    FreeLibrary(hModule);
 
 
    //
    // lpszShellFileName 读取编译好的 Shellcode
    //
    HMODULE hModule2 = LoadLibraryEx(
        lpszShellFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);
    ASSERT(hModule2);
 
    UCHAR *Image2 = (UCHAR *)hModule2;
 
    PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)Image2;
 
    PIMAGE_NT_HEADERS pImageNtHeader = (PIMAGE_NT_HEADERS)
                            (Image2 + pImageDosHeader->e_lfanew);
 
    PIMAGE_SECTION_HEADER pImageSecHeader = (PIMAGE_SECTION_HEADER)
        (Image2 + pImageDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
 
    ULONG sizeOfShell = pImageSecHeader->SizeOfRawData;
 
    UCHAR *c = new UCHAR[sizeOfShell];
    UCHAR *sectionAddress = (UCHAR *)
        (Image2 + pImageSecHeader->VirtualAddress);
 
    ULONG EntryOff = pImageNtHeader->OptionalHeader.AddressOfEntryPoint -
        pImageSecHeader->VirtualAddress;
 
    memcpy(c, sectionAddress, sizeOfShell);
 
    FreeLibrary(hModule2);
     
    //
    // Fix shell code
    //
    char *c2 = (char *)c;
 
    ASSERT(c2[0] == '\xE9');
    *(ULONG *)(&c2[1]) = EntryOff - 5;
 
    // For debug
    //c2[0] = '\xCC';  
 
    while(1)
    {
        if (stricmp(c2, "original_entry") == 0)
        {
            //保存挂钩处代码到 shellcode
            memcpy(c2, entrycode, 5);
        }
         
        if (stricmp(c2, "inject_dllname") == 0)
        {
            //复制 dll 完整路径 !..............................................
            memset(c2, 0x0,0x100);
            strcpy(c2, "dll.dll");
            break;
        }
         
        c2 ++;
    }
     
    //
    *pEntry = AddressOfEntryPoint;
    *pSize = sizeOfShell;
    return c;
}
 
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;
 
    // initialize MFC and print and error on failure
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
        // TODO: change error code to suit your needs
        cerr << _T("Fatal Error: MFC initialization failed") << endl;
        nRetCode = 1;
    }
 
    const char szApplicationName[MAX_PATH] = "C:\\Program Files\\汗!.exe";
 
    char lpszModuleFileName[MAX_PATH] = {0};
    GetModuleFileNameA(NULL, lpszModuleFileName, MAX_PATH);
    CString szModuleFileName(lpszModuleFileName);
    szModuleFileName = szModuleFileName.Left(szModuleFileName.ReverseFind('\\'));
 
    // Shellcode PE 文件
    szModuleFileName += "\\c.bin";
    UCHAR *c = NULL;
    ULONG AddressOfEntryPoint;
    ULONG len ;
    c = _FixShellcode(szApplicationName, &AddressOfEntryPoint, szModuleFileName, &len);
 
    //
    //
    //
    char szCommandLine[0x400] = {0};
    strcpy(szCommandLine, szApplicationName);
     
    STARTUPINFO StartupInfo = {0};
    StartupInfo.cb = sizeof(STARTUPINFO);
    PROCESS_INFORMATION ProcessInformation;
 
    // 
    // 前面说了 你打开进程 暂停  获取 .Eip 也行 挂钩处发生变化!
    //
 
    if (!CreateProcess(szApplicationName, szCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInformation))
    {
        //没释放资源   懒
        return FALSE;
    }
     
 
    LPVOID dst = VirtualAllocEx(ProcessInformation.hProcess, NULL, len, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
    // call
    char  call_c[5] = "\xE8";
    *((ULONG *)&call_c[1]) = (ULONG)dst - AddressOfEntryPoint - 5;
 
    WriteProcessMemory(ProcessInformation.hProcess, (LPVOID)AddressOfEntryPoint, call_c, 5, NULL);
    WriteProcessMemory(ProcessInformation.hProcess, (LPVOID)dst, c, len, NULL);
     
     
    BOOL bRetCode = ResumeThread(ProcessInformation.hThread);
    CloseHandle(ProcessInformation.hProcess);
    CloseHandle(ProcessInformation.hThread);
 
    delete[] c;
 
    return nRetCode;
}

[注意]看雪招聘,专注安全领域的专业人才平台!

上传的附件:
收藏
免费
支持
分享
最新回复 (2)
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
代码不错.......
2011-6-14 20:40
0
雪    币: 33
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
写的不错,看看
2011-6-16 10:20
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

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