有些殼, 如 ExeCrypter 2.2.x 用 OpenProcess("CSRSS.EXE") 的方法來檢測 OD.
其原理如下:
普通進程是沒有 SeDebugPrivilege 的, 這時 OpenProcess(系統進程) 不能成功.
但用 OD 調試時, OpenProcess(系統進程) 成功, 殼利用這一點來檢測 OD.
我們先來看兩個例子.
第一個例子
test.exe
=====================================================================================================
include masm32.inc
.const
szNewline dd 0a0dh
szTitle db 'Process can be opened',0
.data
align 4
hSnap dd 0
pe32 PROCESSENTRY32 <0>
szTemp db 1024 dup (0)
.code
start:
pushad
invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, 0
mov hSnap, eax
lea esi, szTemp
lea ebx, pe32
assume ebx : ptr PROCESSENTRY32
mov [ebx].dwSize, sizeof pe32
invoke Process32First, hSnap, ebx
.while eax
mov eax, [ebx].th32ProcessID
invoke OpenProcess, PROCESS_ALL_ACCESS, 0, eax
.if eax
invoke CloseHandle, eax
lea eax, [ebx].szExeFile
invoke lstrcat, esi, eax
invoke lstrcat, esi, offset szNewline
.endif
invoke Process32Next, hSnap, ebx
.endw
assume ebx : nothing
invoke CloseHandle, hSnap
invoke MessageBox, 0, esi, offset szTitle, MB_OK
popad
invoke ExitProcess, 0
end start
==========================================================================================================
test.exe 是用來快照系統當前的進程, 顯示可以 OpenProcess 的進程.
用和不用 OD 來運行的結果不一樣.
第二個例子
OD1.exe
==================================================================================================================
include masm32.inc
.const
szNewline dd 0a0dh
szOk db 'OK',0
szErr db 'Error',0
szTitle db 'Adjust Debug Privilege',0
szDebugName db 'SeDebugPrivilege',0
szTest db 'test.exe',0
.data
align 4
hToken dd 0
tkp TOKEN_PRIVILEGES <>
pInfo PROCESS_INFORMATION <0>
sInfo STARTUPINFO <0>
szTemp db 1024 dup (0)
.code
; 改變進程的 Debug 權限
AdjustPrivilege proc uses esi, hProcess:dword, bEnable:dword
local retVal : dword
mov retVal, 0
lea esi, tkp
mov dword ptr [esi], 1
.if bEnable
mov dword ptr [esi+0Ch], SE_PRIVILEGE_ENABLED
.else
mov dword ptr [esi+0Ch], 0
.endif
mov eax, esi
add eax, 4
invoke LookupPrivilegeValue, 0, offset szDebugName, eax
.if eax
invoke OpenProcessToken, hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, offset hToken
.if eax
invoke AdjustTokenPrivileges, hToken, 0, esi, 0, 0, 0
mov retVal, eax
invoke CloseHandle, hToken
.endif
.endif
mov eax, retVal
ret
AdjustPrivilege endp
start:
pushad
lea esi, sInfo
mov dword ptr [esi], sizeof STARTUPINFO
invoke GetStartupInfo, esi
invoke CreateProcess, offset szTest, 0, 0, 0, 0, 0, 0, 0, esi, offset pInfo
invoke GetCurrentProcess
invoke AdjustPrivilege, eax, 1
.if eax
invoke MessageBox, 0, offset szOk, offset szTitle, MB_OK
.else
invoke MessageBox, 0, offset szErr,offset szTitle, MB_OK
.endif
invoke GetStartupInfo, esi
invoke CreateProcess, offset szTest, 0, 0, 0, 0, 0, 0, 0, esi, offset pInfo
invoke GetCurrentProcess
invoke AdjustPrivilege, eax, 0
.if eax
invoke MessageBox, 0, offset szOk, offset szTitle, MB_OK
.else
invoke MessageBox, 0, offset szErr,offset szTitle, MB_OK
.endif
invoke GetStartupInfo, esi
invoke CreateProcess, offset szTest, 0, 0, 0, 0, 0, 0, 0, esi, offset pInfo
popad
invoke ExitProcess, 0
end start
=======================================================================================================
這個例子裏示範了怎樣改變本身進程的 SeDebugPrivilege, 並三次創建子進程
1. 普通情況下 CreateProcess(test.exe)
2. Enable SeDebugPrivilege 的情況下 CreateProcess(test.exe)
3. Disable SeDebugPrivilege 的情況下 CreateProcess(test.exe)
注意比較結果, 我們可以明白 OD 是怎麼做的了.
(提升權限大概是爲了調試系統進程吧?)
用 OD 調試一下自己, 我們很容易找到下面的地方.
其中 00435421 中的 2 就是 SE_PRIVILEGE_ENABLED, 把她改成 0, 我們這次的改造就完成了.
用改造好的 OD 調試了一下 ASP, ARM, ExeCrypter 等, 都沒有問題.
其實我們還可以寫一個工具, 不修改 OD, 僅改變 OD 的子進程的權限.
0043537C /$ 53 PUSH EBX
0043537D |. 56 PUSH ESI
0043537E |. 57 PUSH EDI
0043537F |. 83C4 E4 ADD ESP,-1C
00435382 |. 68 C66E4B00 PUSH EXPLORER.004B6EC6 ; /ProcNameOrOrdinal = "OpenProcessToken"
00435387 |. A1 085A4D00 MOV EAX,DWORD PTR DS:[4D5A08] ; |
0043538C |. 50 PUSH EAX ; |hModule => 7C2D0000 (ADVAPI32)
0043538D |. E8 FE9C0700 CALL <JMP.&KERNEL32.GetProcAddress> ; /GetProcAddress
00435392 |. 8BD8 MOV EBX,EAX
00435394 |. 68 D76E4B00 PUSH EXPLORER.004B6ED7 ; /ProcNameOrOrdinal = "LookupPrivilegeValueA"
00435399 |. A1 085A4D00 MOV EAX,DWORD PTR DS:[4D5A08] ; |
0043539E |. 50 PUSH EAX ; |hModule => 7C2D0000 (ADVAPI32)
0043539F |. E8 EC9C0700 CALL <JMP.&KERNEL32.GetProcAddress> ; /GetProcAddress
004353A4 |. 8BF0 MOV ESI,EAX
004353A6 |. 68 ED6E4B00 PUSH EXPLORER.004B6EED ; /ProcNameOrOrdinal = "AdjustTokenPrivileges"
004353AB |. A1 085A4D00 MOV EAX,DWORD PTR DS:[4D5A08] ; |
004353B0 |. 50 PUSH EAX ; |hModule => 7C2D0000 (ADVAPI32)
004353B1 |. E8 DA9C0700 CALL <JMP.&KERNEL32.GetProcAddress> ; /GetProcAddress
004353B6 |. 8BF8 MOV EDI,EAX
004353B8 |. 85DB TEST EBX,EBX
004353BA |. 74 08 JE SHORT EXPLORER.004353C4
004353BC |. 85F6 TEST ESI,ESI
004353BE |. 74 04 JE SHORT EXPLORER.004353C4
004353C0 |. 85FF TEST EDI,EDI
004353C2 |. 75 05 JNZ SHORT EXPLORER.004353C9
004353C4 |> 83C8 FF OR EAX,FFFFFFFF
004353C7 |. EB 7F JMP SHORT EXPLORER.00435448
004353C9 |> 6A 08 PUSH 8 ; /Arg3 = 00000008
004353CB |. 6A 00 PUSH 0 ; |Arg2 = 00000000
004353CD |. 8D5424 08 LEA EDX,DWORD PTR SS:[ESP+8] ; |
004353D1 |. 52 PUSH EDX ; |Arg1
004353D2 |. E8 C9E10600 CALL EXPLORER.004A35A0 ; /EXPLORER.004A35A0
004353D7 |. 83C4 0C ADD ESP,0C
004353DA |. E8 459C0700 CALL <JMP.&KERNEL32.GetCurrentProcess> ; [GetCurrentProcess
004353DF |. 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8]
004353E3 |. 51 PUSH ECX
004353E4 |. 6A 28 PUSH 28
004353E6 |. 50 PUSH EAX
004353E7 |. FFD3 CALL EBX
004353E9 |. 85C0 TEST EAX,EAX
004353EB |. 75 05 JNZ SHORT EXPLORER.004353F2
004353ED |. 83C8 FF OR EAX,FFFFFFFF
004353F0 |. EB 56 JMP SHORT EXPLORER.00435448
004353F2 |> 54 PUSH ESP
004353F3 |. 68 036F4B00 PUSH EXPLORER.004B6F03 ; ASCII "SeDebugPrivilege"
004353F8 |. 6A 00 PUSH 0
004353FA |. FFD6 CALL ESI
004353FC |. 85C0 TEST EAX,EAX
004353FE |. 75 05 JNZ SHORT EXPLORER.00435405
00435400 |. 83C8 FF OR EAX,FFFFFFFF
00435403 |. EB 43 JMP SHORT EXPLORER.00435448
00435405 |> C74424 0C 010>MOV DWORD PTR SS:[ESP+C],1
0043540D |. 6A 08 PUSH 8 ; /Arg3 = 00000008
0043540F |. 8D5424 04 LEA EDX,DWORD PTR SS:[ESP+4] ; |
00435413 |. 52 PUSH EDX ; |Arg2
00435414 |. 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP+18] ; |
00435418 |. 51 PUSH ECX ; |Arg1
00435419 |. E8 12E10600 CALL EXPLORER.004A3530 ; /EXPLORER.004A3530
0043541E |. 83C4 0C ADD ESP,0C
00435421 |. C74424 18 020>MOV DWORD PTR SS:[ESP+18],2 ; 這個2 就是 SE_PRIVILEGE_ENABLED, 改成 0 ***************************
00435429 |. 6A 00 PUSH 0
0043542B |. 6A 00 PUSH 0
0043542D |. 6A 00 PUSH 0
0043542F |. 8D4424 18 LEA EAX,DWORD PTR SS:[ESP+18]
00435433 |. 50 PUSH EAX
00435434 |. 6A 00 PUSH 0
00435436 |. 8B5424 1C MOV EDX,DWORD PTR SS:[ESP+1C]
0043543A |. 52 PUSH EDX
0043543B |. FFD7 CALL EDI
0043543D |. 85C0 TEST EAX,EAX
0043543F |. 75 05 JNZ SHORT EXPLORER.00435446
00435441 |. 83C8 FF OR EAX,FFFFFFFF
00435444 |. EB 02 JMP SHORT EXPLORER.00435448
00435446 |> 33C0 XOR EAX,EAX
00435448 |> 83C4 1C ADD ESP,1C
0043544B |. 5F POP EDI
0043544C |. 5E POP ESI
0043544D |. 5B POP EBX
0043544E /. C3 RETN
//----------------------------------------------------------------------------------------------------------------------
土星按:上面提到的
1. 普通情況下 CreateProcess(test.exe) //只能枚舉少數幾個進程名稱,不包括CSRSS.EXE
2. Enable SeDebugPrivilege 的情況下 CreateProcess(test.exe) //可以枚舉包括CSRSS.EXE在內的進程
3. Disable SeDebugPrivilege 的情況下 CreateProcess(test.exe) //只能枚舉少數幾個進程名稱,不包括CSRSS.EXE
可以看到,在不同權限下面可以看到的進程都不一樣,所以在ollydb原版下面,殼的OpenProcess("CSRSS.EXE")可以成功,但是在用戶態下面OpenProcess("CSRSS.EXE")並不會成功,這個就是檢測ollydb的原理.
當然這個辦法並不算是好辦法,有網友談到:
od用SE_PRIVILEGE_ENABLED用啓用SE_DEBUG_NAME,最好不要禁用。爲什麼要啓用SE_DEBUG_NAME?調試某些進程需要此權限。某些調試API需要此權限。
有沒有更好的辦法呢?有!win32裏面其實沒有父進程的概念,只有從哪個進程繼承數據的概念。同樣這個繼承了SE_DEBUG_NAME.所以,只要改變,讓子進程從explorer繼承就行了。可以使用如下的辦法:Hook ntoskrnl!NtCreateProcessEx,創建被調試進程後,修改EPROCESS.InheritedFromUniqueProcessId爲explorer的pid,
但這樣做xikuge的那個reverseme不能運行,不知爲什麼。<加密技術內幕>裏的antiloader倒是可以通過。
也有網友談到:
權限我是這樣搞的:Hook掉OD自己的WaitForDebugEvent,在收到被調試進程的第1個int3後降低其權限。
殊途同歸