前言
在我们日常编程中,有可能为的只是一个函数的调用的情况,导致我们需要写一个DLL注入到目标进程中。就笔者个人而言,笔者更喜欢集成在一个EXE中。所以这个时候最好的解决方式就是ShellCode。而外面已有的Shellcode编写大部分都是最终生成二进制数据,我个人认为是比较麻烦的。所以这里我带来了一个另类思路。
编写方式
1、构造一个结构体,里面用来填充ShellCode所需要内容。切记禁止有需要间接访问的内容。
1 2 3 4 5 6 7 8
| using MessageBoxW_t = INT(WINAPI*)(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType);
struct ShellCodeInfo { MessageBoxW_t MessageBoxW; const wchar_t* szText; const wchar_t* szCaption; UINT uType; };
|
2、组装参数并把结构体写入到目标进程中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ShellCodeInfo shellcodeInfo{}; shellcodeInfo.MessageBoxW = (MessageBoxW_t)MessageBoxW; const wchar_t szText[]{ L"测试ShellCode" }; const wchar_t szCaption[]{ L"标题" }; memcpy_s((void*)shellcodeInfo.szText, sizeof shellcodeInfo.szText, szText, sizeof szText); memcpy_s((void*)shellcodeInfo.szCaption, sizeof shellcodeInfo.szCaption, szCaption, sizeof szCaption); shellcodeInfo.uType = MB_OK;
LPBYTE lpParamBuff = reinterpret_cast<BYTE*>(VirtualAllocEx(hProcess, nullptr, sizeof(ShellCodeInfo), MEM_COMMIT MEM_RESERVE, PAGE_READWRITE)); if (!lpParamBuff) { break; } if (!WriteProcessMemory(hProcess, lpParamBuff, &shellcodeInfo, sizeof(ShellCodeInfo), nullptr)) { break; }
|
3、准备一个函数,用来当作ShellCode函数。切记禁止写与地址相关的代码。
1 2 3 4
| DWORD RemoteMessageBox(ShellCodeInfo* shellcodeInfo) { shellcodeInfo->MessageBoxW(NULL, shellcodeInfo->szText, shellcodeInfo->szCaption, shellcodeInfo->uType); return 0; }
|
4、将函数当作ShellCode写入目标进程中
1 2 3 4 5 6 7 8
| LPVOID lpShellcode = VirtualAllocEx(hProcess, nullptr, 0x1000, MEM_COMMIT MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!lpShellcode) { break; } if (!WriteProcessMemory(hProcess, lpShellcode, RemoteMessageBox, 0x1000, nullptr)) { break; }
|
5、使用远线程调用该函数
1 2 3 4 5 6 7
| HANDLE hThread = CreateRemoteThread(hProcess, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(lpShellcode), lpParamBuff, 0, nullptr); if (!hThread) { break; } WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread);
|
6、禁用安全检查,防止出现地址相关代码
![2022-12-15T17:05:24.png 2022-12-15T17:05:24.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
问题
该方法使用ShellCode不能在默认的Debug模式下运行,因为Debug模式下会对函数生成与地址有关的代码,所以会导致在目标进程中崩溃。而我们日常开发中可能需要调试其他代码,这就产生了冲突。
解决方案
1、对函数使用static字段修饰,消除跳转表
2、使用调试库设置为否【英文叫Use Debug Libraries】
![l5hv80t5.png l5hv80t5.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
3、支持仅我的代码调试设置为否【英文叫Support Just My Code Debugging】
![l5hv8tqr.png l5hv8tqr.png](https://pan.pigeoooon.cool/d/imgs/blog/loading.gif)
写在最后
如果本文对你有所帮助,请麻烦点赞转发。如果你有更好的Debug模式下保持shellcode干净方式,请留言哦