增加节
BOOL IncreaseSection(PVOID fileName) {
BYTE shellcode[] = { 0x6a,0x00,0x6a,0x00,0x6a,0x00,0x6a,0x00,0xe8,0xD9,0x42,0xcd,0x74,0xe9,0x12,0xc9,0xff,0xff };
//&MessageBox = 750F0D80
//读取到FileBuffer 并且套入Headers
PVOID pFileBuffer = FileToFileBuffer(fileName);
PIMAGE_DOS_HEADER pDosHeader = pFileBuffer;
PIMAGE_NT_HEADERS pNTHeader = (DWORD)pDosHeader + pDosHeader->e_lfanew;
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("File is not PE\n");
free(pFileBuffer);
return FALSE;
}
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = (DWORD)pFileHeader + sizeof(IMAGE_FILE_HEADER);
PIMAGE_SECTION_HEADER pSecHeader = (DWORD)pOptHeader + pFileHeader->SizeOfOptionalHeader;
//计算最后一个节
PIMAGE_SECTION_HEADER pLastSection = pSecHeader + pFileHeader->NumberOfSections - 1;
//不准备做判断后面能不能新添一个节表,无脑往前提就完了,不过还是要判断往前腾出来的空间够不够放下80字节的
DWORD commentAreaSize = pDosHeader->e_lfanew - sizeof(IMAGE_DOS_HEADER);
if (commentAreaSize < 0x80) {
printf("e_lfanew is not enough\n");
free(pFileBuffer);
return FALSE;
}
/*从NtHeader到最后节的结尾中间就是要移动的大小,但是我逻辑能力太差了不理解为什么要加4才是全部的数据(因为测试的时候发现就是
差那个4字节*/
DWORD pNtheaderSize = (DWORD)(pLastSection + 1) - (DWORD)pNTHeader + 4;
memcpy((&pDosHeader->e_lfanew + 1), pNTHeader, pNtheaderSize);
//往前提后所有headers要重新计算...
pDosHeader->e_lfanew -= commentAreaSize;
pNTHeader = (DWORD)pDosHeader + pDosHeader->e_lfanew;
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("File is not PE\n");
free(pFileBuffer);
return FALSE;
}
pFileHeader = &pNTHeader->FileHeader;
pOptHeader = (DWORD)pFileHeader + sizeof(IMAGE_FILE_HEADER);
pSecHeader = (DWORD)pOptHeader + pFileHeader->SizeOfOptionalHeader;
pLastSection = pSecHeader + pFileHeader->NumberOfSections - 1;
memset(((DWORD)(&pDosHeader->e_lfanew) + pNtheaderSize), 0, commentAreaSize);
//增加节表
PIMAGE_SECTION_HEADER pNewSection = pLastSection + 1;
pFileHeader->NumberOfSections += 1;
pOptHeader->SizeOfImage += SIZE_OF_INCREASE_SECTION;
memcpy(pNewSection, pLastSection, sizeof(IMAGE_SECTION_HEADER));
strcpy(pNewSection->Name, ".gggg");
pNewSection->Misc.VirtualSize = SIZE_OF_INCREASE_SECTION;
pNewSection->VirtualAddress = pLastSection->VirtualAddress +
Align(MAX(pLastSection->SizeOfRawData, pLastSection->Misc.VirtualSize), pOptHeader->SectionAlignment);
pNewSection->SizeOfRawData = Align(SIZE_OF_INCREASE_SECTION,pOptHeader->FileAlignment);
pNewSection->PointerToRawData = pLastSection->PointerToRawData + pLastSection->SizeOfRawData;
//关闭随机基址
pOptHeader->DllCharacteristics &= (~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
//更改权限为可执行无脑改
pNewSection->Characteristics |= IMAGE_SCN_MEM_EXECUTE;
//早点构造shellcode和改oep,不然等会儿NewFileBuffer又要重新计算所有headers
DWORD e8Addr = (DWORD)MessageBox - (pOptHeader->ImageBase + pNewSection->VirtualAddress + 8 + 5);
DWORD e9Addr = pOptHeader->AddressOfEntryPoint - (pNewSection->VirtualAddress + 8 + 5 + 5);
*((PDWORD)(shellcode + 9)) = e8Addr;
*((PDWORD)(shellcode + 9 + 5)) = e9Addr;
pOptHeader->AddressOfEntryPoint = pNewSection->VirtualAddress;
//把内存里的FileBuffer写到NewFileBuffer里
DWORD newFileBufferSize = pNewSection->PointerToRawData + pNewSection->SizeOfRawData;
DWORD oldBufferSize = pLastSection->PointerToRawData + pLastSection->SizeOfRawData;
PVOID pNewFileBuffer = malloc(newFileBufferSize);
if (!pNewFileBuffer) {
printf("malloc failed\n");
free(pFileBuffer);
return FALSE;
}
memset(pNewFileBuffer, 0, newFileBufferSize);
memcpy(pNewFileBuffer, pFileBuffer, oldBufferSize);
//计算shellcode写入shellcode 改变OEP
PVOID pWritePosition = (DWORD)pNewFileBuffer + pNewSection->PointerToRawData;
memcpy(pWritePosition, shellcode, sizeof(shellcode));
//存盘
FILE* pFile = fopen("C:\\Users\\12459\\Downloads\\111.exe", "wb");
if (!pFile) {
printf("fopen failed\n");
free(pFileBuffer);
free(pNewFileBuffer);
return FALSE;
}
fwrite(pNewFileBuffer, newFileBufferSize, 1, pFile);
free(pFileBuffer);
free(pNewFileBuffer);
return TRUE;
}
扩大节
BOOL ExpandSection(PVOID fileName) {
//做好准备工作,套入headers
BYTE shellcode[] = { 0x6a,0x00,0x6a,0x00,0x6a,0x00,0x6a,0x00,0xe8,0xD9,0x42,0xcd,0x74,0xe9,0x12,0xc9,0xff,0xff };
PVOID pFileBuffer = FileToFileBuffer(fileName);
PIMAGE_DOS_HEADER pDosHeader = pFileBuffer;
PIMAGE_NT_HEADERS pNTHeader = (DWORD)pDosHeader + pDosHeader->e_lfanew;
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("File is not PE\n");
free(pFileBuffer);
return FALSE;
}
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = (DWORD)pFileHeader + sizeof(IMAGE_FILE_HEADER);
PIMAGE_SECTION_HEADER pSecHeader = (DWORD)pOptHeader + pFileHeader->SizeOfOptionalHeader;
PIMAGE_SECTION_HEADER pLastSectionHeader = pSecHeader + pFileHeader->NumberOfSections - 1;
//修改相关的数据
pLastSectionHeader->Misc.VirtualSize += sizeof(shellcode);
pLastSectionHeader->SizeOfRawData = Align(pLastSectionHeader->Misc.VirtualSize,pOptHeader->FileAlignment);
pOptHeader->SizeOfImage = Align(pLastSectionHeader->VirtualAddress +
pLastSectionHeader->Misc.VirtualSize, pOptHeader->SectionAlignment);
pLastSectionHeader->Characteristics |= IMAGE_SCN_MEM_EXECUTE;
pOptHeader->DllCharacteristics &= (~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
//构造shellcode
DWORD e8Addr = (DWORD)MessageBoxA - (pOptHeader->ImageBase + pLastSectionHeader->VirtualAddress +
pLastSectionHeader->Misc.VirtualSize + 8 + 5);
DWORD e9Addr = (DWORD)pOptHeader->AddressOfEntryPoint - (pLastSectionHeader->VirtualAddress +
pLastSectionHeader->Misc.VirtualSize + 8 + 5 + 5);
*((PDWORD)(shellcode + 9)) = e8Addr;
*((PDWORD)(shellcode + 9 + 5)) = e9Addr;
//计算写入位置偏移,改OEP,之后只需要申请newbuffer,写入shellcode就行了
DWORD pWritePositionOffset = pLastSectionHeader->PointerToRawData + pLastSectionHeader->Misc.VirtualSize;
pOptHeader->AddressOfEntryPoint = pLastSectionHeader->VirtualAddress + pLastSectionHeader->Misc.VirtualSize;
//申请NewFileBuffer写入shellcode,保存成文件
DWORD newFileSize = pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData;
PVOID pNewFileBuffer = malloc(newFileSize);
if (!pNewFileBuffer) {
printf("malloc failed\n");
free(pFileBuffer);
return FALSE;
}
memset(pNewFileBuffer, 0, newFileSize);
memcpy(pNewFileBuffer, pFileBuffer, pWritePositionOffset);
memcpy((DWORD)pNewFileBuffer + pWritePositionOffset, shellcode, sizeof(shellcode));
FILE* pFile = fopen("C:\\Users\\12459\\Downloads\\111.exe", "wb");
if (!pFile) {
printf("fopen failed\n");
free(pFileBuffer);
free(pNewFileBuffer);
return FALSE;
}
fwrite(pNewFileBuffer, newFileSize, 1, pFile);
//这里应该是因为我申请的两个buffer大小一样并且结果也是左手倒右手他就帮我优化了,所以我要加一个判断...
if (pFileBuffer == pNewFileBuffer) {
free(pFileBuffer);
return TRUE;
}
free(pNewFileBuffer);
return TRUE;
}