网络安全 频道

浅析木马服务端的生成技术

你可以在“Resource Type”中随意填写你的资源类型,这个类型名称就是我们将要在FindResource函数的第三个参数lpType中使用的资源类型,我这里以“Server”为例。

这样,我就能够以资源的方式来使用这段数据了。我的代码如下:

BOOL CreateServer()

{

    HRSRC hResInfo;

    HGLOBAL hResData;

    DWORD dwSize, dwWritten;

    HANDLE hFile;

    

// 查找所需的资源

    hResInfo = FindResource( NULL, MAKEINTRESOURCE(IDR_SERVER), "Server" );

    

if

( hResInfo == NULL )

        

return

FALSE;

    

// 获得资源尺寸

    dwSize = SizeofResource( NULL, hResInfo );

    

// 装载资源

    hResData = LoadResource( NULL, hResInfo );

    

if

( hResData == NULL )

        

return

FALSE;

    

// 写文件

    hFile = CreateFile( "C:\\MsgBox.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );

    

if

( hFile == NULL )

        

return

FALSE;

    WriteFile( hFile, (LPCVOID)LockResource( hResData ), dwSize, &dwWritten, NULL );

    CloseHandle( hFile );

    

return

TRUE;

}

到这里,如何生成服务端的问题就已经解决了,现在我来讨论如何自定义服务端的数据。我还是以一个例子来解释这个问题,下面是一段代码,也就是一个MessageBox的调用过程:

TCHAR strContext[] = "Hello, World!";

TCHAR strTitle[] = "Hello";

MessageBox( NULL, strContext, strTitle, MB_OK );

以上代码相对应的汇编代码为:

push 0 

; 最后一个参数MB_OK

lea eax,[ebp-18h]

push eax 

; 第3个参数strTitle

lea ecx,[ebp-10h]

push ecx ;

第2个参数strContext

push 0 

; 第1个参数NULL

call dword ptr [__imp__MessageBoxA@16 (0042a2ac)] 

; 函数调用

也就是说,MessageBox的调用过程是传入了两个字符串地址,那么我们只需要将字符串所指向的内容进行改变,就可以达到修改MessageBox显示结果的目的了。

那么,又如何来确定在MsgBox.exe中那两个字符串的位置呢?在这里,我玩弄了一个小把戏,就是将原来MsgBox.asm的.data段改为:

.data

szTitle db 100 dup(''A'')

szText db 100 dup(''B'')

你也许会对这段代码颇为不解。不过我还是请你先按照上面的步骤将这个新的源文件编译链接,然后再改名为MsgBox.bin,最后导入到客户端的资源中。现在,你可以打开那个二进制资源MsgBox.bin看一看,相信你一定会在某个位置找到像下面这样的东西:

这样一来,你就会很容易地发现,标题的相对偏移量是0x800,文本的相对偏移量是0x864——这也就是我定义那一连串''A''和''B''的用意了。

现在,就可以编写我在本文开始所提到的“MsgBox生成器”了,它的核心代码如下:

HRSRC hResInfo;

HGLOBAL hResData;

DWORD dwSize, dwWritten;

LPBYTE p;

HANDLE hFile;

TCHAR szTitle[100], szText[100];

// 查找所需的资源

hResInfo = FindResource( NULL, MAKEINTRESOURCE( IDR_SERVER ), "Server" );

if

( hResInfo == NULL )

{

    MessageBox( hDlg, "查找资源失败!", "错误", MB_OK | MB_ICONINFORMATION );

    

break

;

}

// 获得资源尺寸

dwSize = SizeofResource( NULL, hResInfo );

// 装载资源

hResData = LoadResource( NULL, hResInfo );

if

( hResData == NULL )

{

    MessageBox( hDlg, "装载资源失败!", "错误", MB_OK | MB_ICONINFORMATION );

    

break

;

}

// 为数据分配空间

p = (LPBYTE)GlobalAlloc( GPTR, dwSize );

if

( p == NULL )

{

    MessageBox( hDlg, "分配内存失败!", "错误", MB_OK | MB_ICONINFORMATION );

    

break

;

}

// 复制资源数据

CopyMemory( (LPVOID)p, (LPCVOID)LockResource( hResData ), dwSize );

// 获取标题和文本,并复制数据

GetDlgItemText( hDlg, IDC_EDT_TITLE, szTitle, 100 );

GetDlgItemText(hDlg, IDC_EDT_TEXT, szText, 100);

CopyMemory( (LPVOID)( p + 0x800 ), (LPCVOID)szTitle, 100 );

CopyMemory( (LPVOID)( p + 0x864 ), (LPCVOID)szText, 100 );

// 创建文件,写数据

hFile = CreateFile( "C:\\MsgBox.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );

if

( hFile != NULL )

    WriteFile( hFile, (LPCVOID)p, dwSize, &dwWritten, NULL );

else

{

    MessageBox( hDlg, "创建文件失败!", "错误", MB_OK | MB_ICONINFORMATION );

    GlobalFree( (HGLOBAL)p );

    

break

;

}

// 收尾工作,释放资源

CloseHandle( hFile );

GlobalFree( (HGLOBAL)p );

到这里,这一技术的核心部分基本上就已经讲完了。对于一个实际的木马程序服务端而言,你只需要把MsgBox的标题和文本替换为相应的端口号和邮件地址就可以了。另外,对于用C/C++、Delphi等高级语言所编写的服务端模板,它的尺寸肯定会大大超过一个汇编写成的程序,这样的话查找要替换的字符串或者数值就肯定会花些时间了。

本文配套代码用SDK编写,在Windows XP Professional + VC 6.0下编译通过。

http://www.cnxhacker.com/Article/program/hacker/200612/7418.html

0
相关文章