Last updated on May 5, 2024 am
                  
                
              
            
            
              
                
                第一步,遍历节表
首先应当遍历节表,找到最后一节。
尝试在该节后找到一段连续的40字节空间,因为节表中每一项的长度是固定的40字节。
找到这块空间,便于我们操作。
寻找连续空间的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | DWORD FindEmptyAddress(void* start, int maxSize, int codeLen) { 	int count = 0; 	int i = 0; 	while (i <= maxSize - codeLen) { 		char *current = (char*)start + i; 		for (int j = 0; j < codeLen; j++) { 			if (current[j] != 0) { 				break; 			} 			count++; 		} 		if (count == codeLen) { 			return (DWORD)current; 		} 		i += count + 1; 		count = 0; 	} 	return 0; }
 
  | 
 
找到连续的空间,确定插入新节的位置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | bool AddSection(lpPEFILE peFile, char* name, int length) { 	lpPEHPE peHeader = peFile->h_pe; 	lpPETable table = peFile->pet;
  	int sections = peHeader->NumberOfSections;
  	 	lpPETable newTable = table + sections;
  	 	DWORD injectEntry = FindEmptyAddress(newTable, 0x28, 0x28);
  	if (injectEntry == 0) { 		return false; 	}
 
 
  | 
 
第二步,复制节
先将最后一节复制到我们找到的这40字节空间中。
这样我们只需要在原节表的结构上修改即可。
1 2 3 4
   |  memcpy(newTable, table + sections - 1, 0x28);
  memcpy(newTable->name, name, 8);
 
  | 
 
第三步,修复节表
新节表复制好了,但是其属性内容不太正常,我们需要修复一下(注意,此处要考虑内存对齐问题)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   |  newTable->PointerToRawData += newTable->SizeOfRawData;
  newTable->VirtualAddress += newTable->VirtualSize;
  newTable->SizeOfRawData = length;
  newTable->VirtualSize = length;
 
  DWORD sectionAlignment = peFile->h_op->SectionAlignment; DWORD alignMod = newTable->VirtualAddress % sectionAlignment; if (alignMod != 0) { 	newTable->VirtualAddress += (sectionAlignment - alignMod); }
 
  DWORD fileAlignment = peFile->h_op->FileAlignment; alignMod = newTable->PointerToRawData % fileAlignment; if (alignMod != 0) { 	newTable->PointerToRawData += (fileAlignment - alignMod); }
 
  | 
 
第四步,修复PE头
1 2 3 4
   |  peFile->h_op->SizeOfImage += length;
  peHeader->NumberOfSections += 1;
 
  | 
 
第五步,初始化新节
此处我就全部用0填充了。
1 2
   | DWORD imageBase = (DWORD)peFile->h_dos; memset((void*)(imageBase + newTable->PointerToRawData), 0, newTable->SizeOfRawData);
 
  | 
 
完整函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
   | bool AddSection(lpPEFILE peFile, char* name, int length) { 	lpPEHPE peHeader = peFile->h_pe; 	lpPETable table = peFile->pet;
  	int sections = peHeader->NumberOfSections; 	 	lpPETable newTable = table + sections; 	DWORD injectEntry = FindEmptyAddress(newTable, 0x28, 0x28);
  	if (injectEntry == 0) { 		return false; 	} 	 	memcpy(newTable, table + sections - 1, 0x28); 	memcpy(newTable->name, name, 8);
  	 	newTable->PointerToRawData += newTable->SizeOfRawData; 	newTable->VirtualAddress += newTable->VirtualSize; 	newTable->SizeOfRawData = length; 	newTable->VirtualSize = length;
  	 	DWORD sectionAlignment = peFile->h_op->SectionAlignment; 	DWORD alignMod = newTable->VirtualAddress % sectionAlignment; 	if (alignMod != 0) { 		newTable->VirtualAddress += (sectionAlignment - alignMod); 	} 	 	DWORD fileAlignment = peFile->h_op->FileAlignment; 	alignMod = newTable->PointerToRawData % fileAlignment; 	if (alignMod != 0) { 		newTable->PointerToRawData += (fileAlignment - alignMod); 	}
  	 	peFile->h_op->SizeOfImage += length; 	peHeader->NumberOfSections += 1;
  	 	DWORD imageBase = (DWORD)peFile->h_dos; 	memset((void*)(imageBase + newTable->PointerToRawData), 0, newTable->SizeOfRawData); 	return true; }
 
  | 
 
                
               
            
            
            
              
              
  
  
    
      PE结构(5)新增节
      http://dubhehub.github.io/blogs/2024050415400062615.html