• 【逆向】对PE结构缩小,拉伸,添加节,写入文本等功能做成c++的类


    昨天闲的蛋疼,一想如果每次完成的作业都需要重新写一次完整的PE结构缩小,放大,写入文件等功能,对于我这个上了年纪的老人来说实在难绷,因此我昨天花了大力气,调试了蛮久的,封装在c++的类里面,结构看起来也清晰,功能我也会按照进度持续更新

    顺便谈谈下一步计划,三期结束,想看看内核的编程,和科锐老钱的那本书,叫啥c++反汇编与逆向分析技术解密,接下来就是看看外挂?未来还是蛮想做反挂的一些职业的

    扯远了,上代码,代码我有时间进行优化,后悔上学期的c++没学很好,淦

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. class Data
    6. {
    7. public:
    8. PIMAGE_DOS_HEADER my_dos;//dos头结构
    9. PIMAGE_FILE_HEADER my_file;//file结构
    10. PIMAGE_OPTIONAL_HEADER32 my_optional;//可选PE头结构
    11. PIMAGE_SECTION_HEADER* my_section ;//节表结构
    12. void* Before_Stretch_Data ; //指向拉伸前的内容
    13. void* Stretch_Data ; //指向拉伸后的内容
    14. void* Shrink_Data ; //指向缩小PE结构的内容
    15. Data()
    16. {
    17. my_dos = nullptr;//dos头结构
    18. my_file = nullptr;//file结构
    19. my_optional = nullptr;//可选PE头结构
    20. my_section = nullptr;//节表结构
    21. Before_Stretch_Data = nullptr; //指向拉伸前的内容
    22. Stretch_Data = nullptr; //指向拉伸后的内容
    23. Shrink_Data = nullptr; //指向缩小PE结构的内容
    24. }
    25. ~Data()
    26. {
    27. if (Before_Stretch_Data != nullptr)
    28. {
    29. free(Before_Stretch_Data);
    30. Before_Stretch_Data = nullptr;
    31. }
    32. if (Stretch_Data != nullptr)
    33. {
    34. free(Stretch_Data);
    35. Stretch_Data = nullptr;
    36. }
    37. if (Shrink_Data != nullptr)
    38. {
    39. free(Shrink_Data);
    40. Shrink_Data = nullptr;
    41. }
    42. }
    43. };
    44. class PE
    45. {
    46. public:
    47. public:
    48. void Readfile(char* filename, Data& my_data); //读取pe文件
    49. void Analyze_PE(Data& my_data); //分析pe结构
    50. void Stretch_PE(Data& my_data); //拉伸pe结构
    51. void Shrink_PE(Data& my_data); //缩小pe结构
    52. void New_Section(char* filename,Data& my_data);//新增节,非扩大节,并写入新的exe文件中
    53. };
    54. void PE::New_Section(char* filename, Data& my_data)
    55. {
    56. unsigned int Size; //Size是新文件的大小,是原来的文件大小加上.VirtualSize和SizeOfRawData较大的那个
    57. Size = my_data.my_optional->SizeOfHeaders;
    58. for (int i = 0;i < my_data.my_file->NumberOfSections; i++)
    59. {
    60. Size += my_data.my_section[i]->SizeOfRawData;
    61. }
    62. Size+= my_data.my_section[0]->SizeOfRawData;//这是最终新的文件的大小
    63. Data New_Data;
    64. New_Data.Before_Stretch_Data = (void*)malloc(Size);
    65. memset(New_Data.Before_Stretch_Data, 0, Size);
    66. memcpy_s(New_Data.Before_Stretch_Data, Size, my_data.Before_Stretch_Data, Size - my_data.my_section[0]->SizeOfRawData);//将原来的文件复制过来
    67. Analyze_PE(New_Data);//让New_Data的dos,file,optional,section有数据
    68. //复制新的节表
    69. void* Temp_ptr1 = (char*)my_data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader;
    70. void* Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader + my_data.my_file->NumberOfSections * 0x28;
    71. memcpy_s(Temp_ptr2, 0x28, Temp_ptr1, 0x28);
    72. //复制新的节
    73. Temp_ptr1 = (char*)my_data.Before_Stretch_Data + my_data.my_optional->SizeOfHeaders;//指向.text段
    74. Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + Size - my_data.my_section[0]->SizeOfRawData;
    75. memcpy_s(Temp_ptr2, my_data.my_section[0]->SizeOfRawData, Temp_ptr1, my_data.my_section[0]->SizeOfRawData);//复制完.text段作为新增节
    76. //接下来要改Header的各项数据
    77. New_Data.my_file->NumberOfSections++;
    78. New_Data.my_optional->SizeOfImage += my_data.my_section[0]->SizeOfRawData;
    79. Analyze_PE(New_Data);
    80. New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->PointerToRawData = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->PointerToRawData + New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData;
    81. int size;
    82. if (New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize >= New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData)
    83. {
    84. size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize;
    85. }
    86. else
    87. {
    88. size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData;
    89. }
    90. size = size / my_data.my_optional->SectionAlignment + my_data.my_optional->SectionAlignment;
    91. New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->VirtualAddress = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->VirtualAddress+size;
    92. FILE* my_file;
    93. if (fopen_s(&my_file, filename, "wb") == 0)
    94. {
    95. fwrite(New_Data.Before_Stretch_Data, 1, Size, my_file);
    96. cout << "写入成功!" << endl;
    97. return;
    98. }
    99. else
    100. {
    101. cout << "打开文件失败" << endl;
    102. return;
    103. }
    104. }
    105. void PE::Readfile(char* filename,Data& my_data)
    106. {
    107. unsigned int size;
    108. FILE* datafile;
    109. void* data;
    110. //打开文件
    111. if (fopen_s(&datafile, filename, "rb") != 0)
    112. {
    113. cout << "打开文件失败" << endl;
    114. return;
    115. }
    116. else
    117. {
    118. //获取文件的大小
    119. cout << "打开文件成功!" << endl;
    120. fseek(datafile, 0, SEEK_END);
    121. size = ftell(datafile);
    122. fseek(datafile, 0, SEEK_SET);
    123. if (size == -1L)
    124. {
    125. cout << "文件大小判断失败!" << endl;
    126. return;
    127. }
    128. //申请内存空间把文件内容保存下来
    129. my_data.Before_Stretch_Data = (void*)malloc(size * sizeof(char));
    130. if (fread_s(my_data.Before_Stretch_Data, size, sizeof(char), size, datafile) == 0)
    131. {
    132. cout << "写入数据失败!" << endl;
    133. return;
    134. }
    135. cout << "写入数据成功,成功获取Data!" << endl;
    136. return ;
    137. }
    138. }
    139. //分析PE结构
    140. void PE::Analyze_PE(Data& my_data)
    141. {
    142. DWORD* Temp_ptr = (DWORD*)my_data.Before_Stretch_Data;
    143. my_data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;
    144. Temp_ptr = (DWORD*)((char*)my_data.Before_Stretch_Data+ my_data.my_dos->e_lfanew);
    145. Temp_ptr++;
    146. my_data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;
    147. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
    148. my_data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;
    149. Temp_ptr = (DWORD*)((char*)my_data.my_optional + my_data.my_file->SizeOfOptionalHeader);
    150. my_data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER) * my_data.my_file->NumberOfSections);
    151. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    152. {
    153. my_data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
    154. Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
    155. }
    156. }
    157. //拉伸PE结构 注意看PIMAGE_XXX_HEADER的定义,它们本就是指向结构体的指针
    158. void PE::Stretch_PE(Data& my_data)
    159. {
    160. unsigned Memory_Size = 0;
    161. Memory_Size = my_data.my_optional->SizeOfImage;
    162. my_data.Stretch_Data = (void*)malloc(sizeof(char) * Memory_Size);
    163. memset(my_data.Stretch_Data, 0, Memory_Size);
    164. void* temp_before_stretch_data_ptr = my_data.Before_Stretch_Data;
    165. int size_of_dos = 0x40;
    166. int size_of_junk = 0x40;
    167. int size_of_file = 0x18;
    168. unsigned Size_Of_Optional = my_data.my_file->SizeOfOptionalHeader;
    169. unsigned Size_Of_Section = 0x28;
    170. unsigned Size_Of_Header = size_of_dos + size_of_file + size_of_junk + Size_Of_Optional + Size_Of_Section * my_data.my_file->NumberOfSections;//还未对齐
    171. memcpy_s(my_data.Stretch_Data, Memory_Size, my_data.Before_Stretch_Data, Size_Of_Header);
    172. void* temp_stretch_data = my_data.Stretch_Data;
    173. //现在计算head头对齐后的大小
    174. int Size = Size_Of_Header % my_data.my_optional->SectionAlignment;
    175. Size_Of_Header = my_data.my_optional->SectionAlignment * Size;
    176. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    177. {
    178. temp_stretch_data = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
    179. temp_before_stretch_data_ptr = (void*)((char*)my_data.Before_Stretch_Data + my_data.my_section[i]->PointerToRawData);
    180. memcpy_s(temp_stretch_data, my_data.my_section[i]->SizeOfRawData, temp_before_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
    181. }
    182. cout << "拉伸成功" << endl;
    183. }
    184. void PE::Shrink_PE(Data& my_data)
    185. {
    186. unsigned int Size = 0;
    187. Size = my_data.my_section[my_data.my_file->NumberOfSections - 1]->PointerToRawData + my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
    188. my_data.Shrink_Data = (void*)malloc(Size);
    189. //从Stretch_Data缩小
    190. //复制Heads
    191. memcpy_s(my_data.Shrink_Data, my_data.my_optional->SizeOfHeaders, my_data.Stretch_Data, my_data.my_optional->SizeOfHeaders);
    192. //复制节
    193. void* temp_shrink_data_ptr = my_data.Shrink_Data;
    194. void* temp_stretch_data_ptr = my_data.Stretch_Data;
    195. for (int i = 0; i < my_data.my_file->NumberOfSections; i++)
    196. {
    197. temp_shrink_data_ptr = (void*)((char*)my_data.Shrink_Data + my_data.my_section[i]->PointerToRawData);
    198. temp_stretch_data_ptr = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
    199. memcpy_s(temp_shrink_data_ptr, my_data.my_section[i]->SizeOfRawData, temp_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
    200. }
    201. cout << "缩小成功" << endl;
    202. return;
    203. }
    204. int main()
    205. {
    206. char filename[100]= "ceshi.exe";
    207. PE my_pe;
    208. Data my_data;
    209. my_pe.Readfile(filename,my_data);
    210. my_pe.Analyze_PE(my_data); //char*& Data, PIMAGE_DOS_HEADER& dos, PIMAGE_FILE_HEADER& file, PIMAGE_OPTIONAL_HEADER32& optional, PIMAGE_SECTION_HEADER*& section
    211. my_pe.Stretch_PE(my_data);
    212. my_pe.Shrink_PE(my_data);
    213. char filename2[100] = "666.exe";
    214. my_pe.New_Section(filename2, my_data);
    215. return 0;
    216. }

    不知道大家看别人代码的时候,会不会很讨厌别人使用一些奇奇怪怪的宏定义,明明非常简单的一些指针,除非是结构体指针,确实蛮好用的,但是有些我实在难以理解,于是我的代码几乎没有那些奇奇怪怪的宏定义,主要是自己看着也舒服(其实是我水平确实不高,对比其他人,开发水平实在低)。所以我的代码应该还是很好读懂的

    顺便说下,新增节的功能默认是复制第一个节表和第一个节的内容,如果有需要,可以自己稍加修改,我这只是写了个框架

    WARING:注意注意,如果代码有更新,有新的功能的话,点我主页看!

  • 相关阅读:
    libevent源码学习笔记
    mkv文件怎样转成mp4
    【算法】折半查找解析
    C++:重定义:符号重定义:变量重定义(三):解决变量重定义(声明extern外部变量)
    【Try to Hack】ip地址
    CV经典任务(一) 语义分割、实例分割 | 全卷积
    Spring Boot整合Redis实现订单超时处理
    高并发高可用之ElasticSearch
    使用GPT和FastAPI构建智能数据库查询服务器
    产品经理专业知识50篇(七)-如何建立一套完整的用户成长体系?
  • 原文地址:https://blog.csdn.net/fzucaicai/article/details/133489860