概述
ServiceMain函数的参数通常有两个:第一个是argc(参数数量),第二个是argv(参数数组的指针)。
根据Windows服务DLL的结构,ServiceMain的声明应该是类似VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)。
所以当进入ServiceMain时,ebp+8的位置是argc,而ebp+0xC的位置是argv,也就是指向参数数组的指针。
所以这条指令mov edi, [ebp+0xC] 应该是将argv的地址加载到EDI寄存器中。
下一条指令mov eax, dword ptr ds:[edi] 就是获取argv的第一个元素,也就是服务名。比如,argv[0]通常是服务名称的字符串指针。
使用rundll调试
edi是rundll32的MZ头,导致后续异常
使用服务调试
edi是服务名的地址的地址,二级指针
想办法构造ServiceMain的参数就可以使用rundll32调试服务型dll
构建服务调试步骤
使用下面代码设置服务,
参数1:32位或64位
参数2:svchost路径,建议复制svchost为其他名字,便于后续调试寻找
参数3:dll路径
@echo off set SERVICENAME=001 set ARCH=%1 set SVCPATH=%2 set BINPATH=%3 if "%ARCH%"=="" ( echo "Missing architecture parameter (32 or 64)" exit /b 1 ) if "%SVCPATH%"=="" ( echo "Missing service path parameter" exit /b 1 ) if "%BINPATH%"=="" ( echo "Missing binary path parameter" exit /b 1 ) if "%ARCH%"=="32" ( set BASEPATH=%SYSTEMROOT%\SysWOW64 set REG=HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Svchost ) else if "%ARCH%"=="64" ( set BASEPATH=%SYSTEMROOT%\System32 set REG=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost ) else ( echo "Invalid architecture: %ARCH% (must be 32 or 64)" exit /b 1 ) sc create "%SERVICENAME%" binPath= "%SVCPATH% -k %SERVICENAME%" type= share start= demand if %errorlevel% neq 0 ( echo Failed to create service exit /b %errorlevel% ) reg add "HKLM\System\CurrentControlSet\Services\%SERVICENAME%\Parameters" /v ServiceDLL /t REG_EXPAND_SZ /d "%BINPATH%" /f if %errorlevel% neq 0 ( echo Failed to add ServiceDLL registry entry exit /b %errorlevel% ) reg add "%REG%" /v %SERVICENAME% /t REG_MULTI_SZ /d "%SERVICENAME%\0" /f if %errorlevel% neq 0 ( echo Failed to add Svchost registry entry exit /b %errorlevel% )
然后我们将ServiceMain的入口某处修改为FE EB,让其陷入自循环,后续我们附加就可以找到
然后启动服务,用调试器附加改过名字的svchost,调试即可