x64dbg 实现插件Socket反向通信

2022-12-28 18:24:10 浏览数 (2)

编写一个带有socket通信功能的插件,x64dbg运行后,用户点击链接按钮可直接连接到外部的python中,python作为服务端,当x64dbg内部出现某个事件后,自动将消息推送到外部python脚本上,实现反向传参的目的。

首先编写插件端代码,代码中直接初始化套接字,用户服务端启动后点击connect按钮链接到服务端,链接成功后,一但调试器加载了程序则自动触发CBINITDEBUG(CBTYPE cbType, PLUG_CB_INITDEBUG* info)回调函数,并通过socket将参数送出到外部。

代码语言:javascript复制
#include "pluginmain.h"
#include <Windows.h>
#include <process.h>

#pragma comment(lib,"ws2_32.lib")
#define IP "127.0.0.1"
#define PORT 9999

int pluginHandle;
HWND hwndDlg;
int hMenu;
int hMenuDisasm;
int hMenuDump;
int hMenuStack;

WSADATA WSAData;
SOCKET sock;
struct sockaddr_in ClientAddr;

// 在这里初始化插件数据。
bool pluginInit(PLUG_INITSTRUCT* initStruct)
{
	// 返回false以取消加载插件。
	return true;
}

// 在此处取消初始化插件数据。
void pluginStop()
{
}

// 在这里做GUI/菜单相关的事情。
void pluginSetup()
{
}

// 导出函数
extern "C" __declspec(dllexport) void plugsetup(PLUG_SETUPSTRUCT* setupStruct);
extern "C" __declspec(dllexport) bool pluginit(PLUG_INITSTRUCT* initStruct);

// 导出自定义的两个功能
extern "C" __declspec(dllexport) void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY* info);
extern "C" __declspec(dllexport) void CBINITDEBUG(CBTYPE cbType, PLUG_CB_INITDEBUG* info);

// 菜单回调函数(初始化时自动发送套接字)附加进程触发
void CBINITDEBUG(CBTYPE cbType, PLUG_CB_INITDEBUG* info)
{
	send(sock, (char *)&info, 1024, 0);
	_plugin_logprintf("size = %d n", sizeof(PLUG_CB_INITDEBUG));
	_plugin_logprintf("func = %s n", info->szFileName);
}

// --------------------------------------------------------------------
// 基础功能
// --------------------------------------------------------------------

// 命令触发: 开启Socket的命令
bool ConnectSocket(int argc, char **argv)
{
	_plugin_logprintf("start socket n");

	if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
	{
		ClientAddr.sin_family = AF_INET;
		ClientAddr.sin_port = htons(PORT);
		ClientAddr.sin_addr.s_addr = inet_addr(IP);
	}

	sock = socket(AF_INET, SOCK_STREAM, 0);
	int Ret = connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr));
	return Ret;
}

// 命令触发: 关闭Socket的命令
bool CloseSocket(int argc, char **argv)
{
	_plugin_logprintf("stop socket n");

	send(sock, "SocketClose", 11, 0);
	closesocket(sock);
	WSACleanup();
	return true;
}

// 菜单被点击触发此回调
void CBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY* info)
{
	switch (info->hEntry)
	{
	case 1:
		ConnectSocket(0, 0);
		break;
	case 2:
		CloseSocket(0, 0);
		break;
	}
}

PLUG_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
{
	initStruct->pluginVersion = PLUGIN_VERSION;
	initStruct->sdkVersion = PLUG_SDKVERSION;
	strncpy_s(initStruct->pluginName, PLUGIN_NAME, _TRUNCATE);
	pluginHandle = initStruct->pluginHandle;

	// 插件初始化
	const char *name = "LyScriptCallBack";
	memset(initStruct->pluginName, 0, 128);
	memcpy(initStruct->pluginName, name, strlen(name));

	return pluginInit(initStruct);
}

PLUG_EXPORT bool plugstop()
{
	pluginStop();
	return true;
}

PLUG_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
{
	hwndDlg = setupStruct->hwndDlg;
	hMenu = setupStruct->hMenu;
	hMenuDisasm = setupStruct->hMenuDisasm;
	hMenuDump = setupStruct->hMenuDump;
	hMenuStack = setupStruct->hMenuStack;

	// 增加连接选项
	char sub_connect[] = "Connect";
	_plugin_menuaddentry(setupStruct->hMenu, 1, sub_connect);

	// 添加关闭连接选项
	char sub_close[] = "CloseConnect";
	_plugin_menuaddentry(setupStruct->hMenu, 2, sub_close);

	// 注册ConnectSocket开启Socket命令
	_plugin_registercommand(pluginHandle, "ConnectSocket", ConnectSocket, true);

	// 注册CloseSocket关闭Socket命令
	_plugin_registercommand(pluginHandle, "CloseSocket", CloseSocket, true);

	pluginSetup();
}

客户端则负责接收参数,收到后直接使用MyStruct(Structure)类,格式化为特定结构体,并输出内部成员参数。

代码语言:javascript复制
import socket
import struct
from ctypes import *

ip_addr=("localhost",9999)

server = socket.socket()
server.bind(ip_addr)
server.listen(5)

class MyStruct(Structure):
    _pack_ = 1
    _fields_ = [
        ("szFileName", c_char * 256)
    ]

    def unpack(self,buffer):
        (self.szFileName) = struct.unpack("< 256s",buffer)

while True:
    conn,addr=server.accept()
    print(addr)

    while True:
        try:
            recv_data = str(conn.recv(8192), encoding="utf-8")

            if len(recv_data) == 11 and recv_data == "SocketClose":
                conn.close()
                print("close")
            else:
                recv_struct = MyStruct()
                recv_struct.unpack(recv)
                print(recv_struct.szFileName)

        except Exception:
            break
            server.close()

首先运行python脚本让其侦听特定端口,然后再x64dbg中点击connect链接按钮,链接成功后即可看到输出信息。

0 人点赞