首页
社区
课程
招聘
[原创]用C代实现远程线程(无dll)
发表于: 2008-4-11 00:24 18005

[原创]用C代实现远程线程(无dll)

2008-4-11 00:24
18005

近日拜读了罗云彬先生写的远程线程代码后,心里佩服不已。
就想自己也写一个练练,由于自己水平不高,在写的过程中遇到不小困难,小小的百来行代码写我一个多星期。
现在把代码贴出来请各位前来“挑挑刺”。
编译平台:Windows 2003,Visual c++ 2003。编译的时候要用Release,否则代码运行不了。下面符上代码,和符件(所有代码和程序)。
#include "win32.h"
#define MAX_SIZE 19

char * szData[MAX_SIZE] = {
  "Kernel32.dll",
  "LoadLibraryA",
  "GetProcAddress",
  "GetModuleHandleA",
  "GDI32.dll",
  "User32.dll",
  "DestroyWindow",
  "PostQuitMessage",
  "DefWindowProcA",
  "LoadCursorA",
  "LoadIconA",
  "RegisterClassExA",
  "CreateWindowExA",
  "ShowWindow",
  "UpdateWindow",
  "GetMessageA",
  "TranslateMessage",
  "DispatchMessageA",
  "MessageBoxA"
};

int _WinMain(LPARAM);
ATOM _MyRegisterClass(HINSTANCE, LPARAM);
BOOL _InitInstance(HINSTANCE hInstance, int, LPARAM);
LRESULT __stdcall _WndProc(HWND, UINT, WPARAM, LPARAM);
DWORD WINAPI RemoteThread(LPARAM);

#pragma code_seg("CodeSeg2")

//导入函数地址表
__declspec(allocate("CodeSeg2"))DWORD lpLoadLibrary=0;  
__declspec(allocate("CodeSeg2"))DWORD lpGetProcAddress=0;
__declspec(allocate("CodeSeg2"))DWORD lpGetModuleHandle=0;
__declspec(allocate("CodeSeg2"))DWORD lpDestroyWindow=0;
__declspec(allocate("CodeSeg2"))DWORD lpPostQuitMessage=0;
__declspec(allocate("CodeSeg2"))DWORD lpDefWindowProc=0;
__declspec(allocate("CodeSeg2"))DWORD lpLoadCursor=0;
__declspec(allocate("CodeSeg2"))DWORD lpLoadIcon=0;
__declspec(allocate("CodeSeg2"))DWORD lpRegisterClassEx=0;
__declspec(allocate("CodeSeg2"))DWORD lpCreateWindowEx=0;
__declspec(allocate("CodeSeg2"))DWORD lpShowWindow=0;
__declspec(allocate("CodeSeg2"))DWORD lpUpdateWindow=0;
__declspec(allocate("CodeSeg2"))DWORD lpGetMessage=0;
__declspec(allocate("CodeSeg2"))DWORD lpTranslateMessage=0;
__declspec(allocate("CodeSeg2"))DWORD lpDispatchMessage=0;
__declspec(allocate("CodeSeg2"))DWORD lpMessageBox=0;

//全局变量:
__declspec(allocate("CodeSeg2"))DWORD _hInstance=0;      
__declspec(allocate("CodeSeg2"))DWORD _hWinMain=0;
//字符串表
__declspec(allocate("CodeSeg2"))char _szClassName[]="RemoteClass";
__declspec(allocate("CodeSeg2"))char _szCaptionMain[]="RemoteWindow";

LRESULT __stdcall _WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  DWORD lOffset;

  __asm{
    push edx
    call lab
    lab:
    pop edx
    sub edx, lab
    mov lOffset, edx
    pop edx
  }

  switch (message) 
  {
  case WM_DESTROY:
    ReloCationForLP(lpPostQuitMessage,lOffset)(0);
    break;
  default:
    return ReloCationForLP(lpDefWindowProc,lOffset)(hWnd, message, wParam, lParam);
  }

  return 0;
}

DWORD WINAPI RemoteThread(LPARAM lParam){
  ReloCationForDWORD(_hInstance,lParam) = DWORD(ReloCationForLP(lpGetModuleHandle,lParam)(NULL));
  _WinMain(lParam);
  return 0;
}
int _WinMain(LPARAM lParam){
  HINSTANCE hInstance = HINSTANCE(ReloCationForDWORD(_hInstance, lParam));
  MSG Message;

  _MyRegisterClass(hInstance, lParam);
  
  if(!_InitInstance(hInstance, SW_SHOWNORMAL, lParam))
    return FALSE;

  while(ReloCationForLP(lpGetMessage, lParam)(&Message,0,0,0)){
    ReloCationForLP(lpTranslateMessage, lParam)(&Message);
    ReloCationForLP(lpDispatchMessage, lParam)(&Message);
  }

  return int(Message.wParam);
}
ATOM _MyRegisterClass(HINSTANCE hInstance, LPARAM lParam)
{
  WNDCLASSEX wcex;
  wcex.cbSize = sizeof(WNDCLASSEX); 

  wcex.style      = CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc  = WNDPROC(DWORD(&_WndProc) + DWORD(lParam));
  wcex.cbClsExtra    = 0;
  wcex.cbWndExtra    = 0;
  wcex.hInstance    = hInstance;
  wcex.hIcon      = ReloCationForLP(lpLoadIcon, lParam)(NULL, IDC_ICON);
  wcex.hCursor    = ReloCationForLP(lpLoadCursor, lParam)(NULL, IDC_ARROW);
  wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
  wcex.lpszMenuName  = 0;
  wcex.lpszClassName  = ReloCataonForTCHAR(_szClassName, lParam);
  wcex.hIconSm    = ReloCationForLP(lpLoadIcon, lParam)(NULL, IDC_ICON);
  return ReloCationForLP(lpRegisterClassEx,lParam)(&wcex);
}

BOOL _InitInstance(HINSTANCE hInstance, int nCmdShow, LPARAM lParam)
{
  HWND hWnd;
   hWnd = ReloCationForLP(lpCreateWindowEx,lParam)(WS_EX_CLIENTEDGE, ReloCataonForTCHAR(_szClassName, lParam), 
    ReloCataonForTCHAR(_szCaptionMain, lParam), WS_OVERLAPPEDWINDOW,
      100, 100, 600, 400, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ReloCationForLP(lpShowWindow,lParam)(hWnd, nCmdShow);
   ReloCationForLP(lpUpdateWindow,lParam)(hWnd);

   return TRUE;
}
#pragma code_seg()

// win32.cpp : 定义应用程序的入口点。
//
int __stdcall Enter()
{
  DWORD dwProcessID;
  HANDLE hProcess, hThread;
  LPVOID lpBaseAddress;  //远程线程基址
  LPTHREAD_START_ROUTINE lpStartAddress;  //远程线程入口地址
  HMODULE hModule = 0;

  DWORD hMod = DWORD(GetModuleHandle(NULL));
  PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
    PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew );
    PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr );
  for (unsigned i = 0;i < pNtHdr->FileHeader.NumberOfSections;i++, pSection++ )
    if (!strncmp("CodeSeg2",(char *)(pSection->Name),8)) break;

  LPDWORD lpData = LPDWORD(&lpLoadLibrary);
  for(int i = 0; i < MAX_SIZE; i ++){
    *lpData = (DWORD)GetProcAddress(hModule, szData[i]);
    if (*lpData) lpData ++;
    else hModule = GetModuleHandle(szData[i]);
  }
  GetWindowThreadProcessId(FindWindow(TEXT("Progman"),TEXT("Program Manager")), &dwProcessID);
  hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessID);
  if(hProcess){
    lpBaseAddress = VirtualAllocEx(hProcess, NULL, pSection->SizeOfRawData, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if(lpBaseAddress){
      lpStartAddress = LPTHREAD_START_ROUTINE(DWORD(lpBaseAddress) + DWORD(RemoteThread) - DWORD(&lpLoadLibrary));
      WriteProcessMemory(hProcess, lpBaseAddress, LPVOID(&lpLoadLibrary), pSection->SizeOfRawData, NULL);
      hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, LPVOID(DWORD(lpBaseAddress) - DWORD(&lpLoadLibrary)), 0, NULL);
//      WaitForSingleObject(hThread,INFINITE);
//      VirtualFreeEx(hProcess, lpBaseAddress, 0, MEM_RELEASE);
      CloseHandle(hThread);
    }
    CloseHandle(hProcess);
  }
  else{
    MessageBox(NULL, TEXT("无法打开进程!"), TEXT("错误"), 0);
  }

  return 0;
}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (24)
雪    币: 224
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
沙发……
学习………………
2008-4-11 08:05
0
雪    币: 224
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
#define ReloCationForLP(x1,x2) (__##x1(ReloCationForDWORD(x1,x2)))

楼主,这是什么意思????
没看懂~~~
ReloCationForDWORD(x1,x2)本来就是取得的x1的重定位后的值
又把它变成__x1(Address)????
(基础太差………… )
2008-4-11 08:40
0
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
4
写得不错,学习
2008-4-11 08:57
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
5
远程线程本来就可以不要dll.

《WINDOWS核心编程》有完整的code和详细的说明分析。

很古老的东西了啊
2008-4-11 10:18
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
比如说:ReloCationForLP(lpUpdateWindow,lParam)(hWnd)
ReloCationForDWORD(x1,x2)取得x1的重定位后的值
最后变成__lpUpdateWindow(Address)。

"__pUpdateWindow"在头文件有定义:
typedef BOOL (__stdcall *__lpUpdateWindow)(
  HWND
  );
2008-4-11 10:23
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
老罗的代码我也是今年才看到,也是看了他的代码才知道远程线程这个东西,现在只是写来练练。
2008-4-11 10:26
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
8
写得很不错~~

给个小建议:
把重定位的代码剥离出来,重新写一个函数
  __asm{
    push edx
    call lab
    lab:
    pop edx
    sub edx, lab
    mov lOffset, edx
    pop edx
  }

上面这段代码不要写在某个过程里面,单独拿出来
__declspec(naked) DWORD GetDelta()
{
__asm
{
	call next
next:
	pop eax
	sub eax,offset next
	ret
}
}

然后要获取delta的时候,调用一下GetDelta就可以了

比如:
DWORD lOffset = GetDelta();

内嵌进去如果寄存器用不好会出现可爱的错误

To sudami:远程线程是古老的技术,但楼主这篇文章的价值在于高效地维护这段远程线程代码,试想用汇编去实现复杂的远程线程功能,要写多少代码,维护起来有多麻烦

如果我是版主,肯定给精华了
2008-4-11 11:50
0
雪    币: 398
活跃值: (343)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
9
fengyue说好就是好
2008-4-11 11:53
0
雪    币: 8209
活跃值: (4518)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
10
支持fengyue申请版主
2008-4-11 12:09
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
等于把所有的代码都复制到远程进程去了,小的话还可以,如果远程做的事非常多的话

还是DLL比较方面,也省心省力
2008-4-11 13:52
0
雪    币: 70
活跃值: (74)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
是不错!    虽然直接写DLL更有实效性
2008-4-11 18:30
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习了几个VC的用法,不错
2008-4-11 18:52
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
谢谢海风月影的建议。多谢版主给加精
2008-4-12 12:12
0
雪    币: 22
活跃值: (458)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
不错 学习了.
2008-4-12 14:18
0
雪    币: 235
活跃值: (23)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
16
我觉得还是用汇编简单
2008-4-12 18:02
0
雪    币: 107
活跃值: (1693)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
17
一下下来 卡巴就叫个不停
2008-4-12 20:12
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
18
很强大,学习了
2008-4-12 20:16
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
19
放心不是病毒的。
2008-4-12 23:21
0
雪    币: 8
活跃值: (2686)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
很强很暴力。
2008-4-14 09:52
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
赞个,思路不错

不过这样写代码比用汇编都累,而且你也不能完全确定编译器产生的其他部分的代码是可重定位的
2008-4-14 10:57
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
在网吧试了一下,蓝屏了。XP SP2
2008-4-26 09:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
第一次听说,学习了
2008-5-26 19:00
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
学习学习!!!
2008-5-27 08:05
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
好东西,正要使用
2011-8-2 15:55
0
游客
登录 | 注册 方可回帖
返回
//