滴水逆向 FileBuffer--->ImageBuffer

上节课说到遍历节表,这节课让我们把FileBuffer-->ImageBuffer

海哥让我们用notepad.exe因为他的文件对齐和内存对齐是不一样的,如果一样的化,FileBuffer和ImageBuffer是一样的,为什么ImageBuffer还是不能执行呢?因为ImageBuffer的地址是我们malloc出来的,首地址不是ImageBase。

写代码之前我们需要掌握几个知识点

1.ImageBuffer的大小是多少?

我们不能直接把FileBuffer复制过来,因为notepad.exe的FileBuffer没有拉伸,我们回想PE结构,OptionalHeader有一个属性记载着ImageBuffer的大小,那就是SizeOfImage。

2.FileBuffer和ImageBuffer的Headers是没有区别的,头部没有拉伸,直接复制过来即可

3.如何复制节表?

因为FileBuffer和ImageBuffer的区别就是节表在内存中的位置不同,我们要一个一个节表的循环复制,那么我们要复制几次?FilePE头的NumberOfSection参数记录这节表的数量。我们要从哪里开始复制复制多少?节表里给出了答案。我们要从FileBuffer的PointerToRawData开始复制到ImgaeBuffer的VirtualAddress,复制SizeOfRawData的大小。

4.这里用到了二级指针,为什么要用到二级指针?因为当一个函数要返回两个参数的时候,就要用到二级指针。

5.当我们ImageBuffer——>NewBuffer的时候,我们怎么知道NewBuffer开辟malloc的大小?

因为Headers是一样的,我们只需要看节表就行,我们首先要循环到最后一个节表,找到PointerToRawData也就是在文件中的偏移,然后再找到SizeOfRawData也就是文件对齐后的大小,这两个相加就是NewBuffer的大小(记得把SectionHeader的指针还原,因为后面还需要遍历)

代码:

#include "stdafx.h"
#include<stdio.h>
#include<windows.h>
#include<malloc.h>
//
//FileBuffer函数
DWORD ReadPEFile(LPVOID* ppFileBuffer)
{
	FILE* pFile=NULL;
	DWORD SizeFileBuffer=0;
	pFile=fopen("C://WINDOWS//system32//notepad.exe","rb");
	if(!pFile)
	{
		printf("打开notepad失败\n");
		return 0;
	}
	//获取文件大小
	fseek(pFile,0,SEEK_END);
	SizeFileBuffer=ftell(pFile);
	fseek(pFile,0,SEEK_SET);
	if(!SizeFileBuffer)
	{
		printf("读取文件大小失败\n");
		return 0;
	}
	//开辟空间
	*ppFileBuffer=malloc(SizeFileBuffer);
	if(!*ppFileBuffer)
	{
		printf("开辟空间失败\n");
		fclose(pFile);
		return 0;
	}
	//复制数据
	size_t n=fread(*ppFileBuffer,SizeFileBuffer,1,pFile);
	if(!n)
	{
		printf("复制数据失败\n");
		free(*ppFileBuffer);
		fclose(pFile);
		return 0;
	}
	fclose(pFile);
	return SizeFileBuffer;
}



///
//FileBuffer--->ImgaeBuffer
DWORD FileBufferToImageBuffer(LPVOID pFileBuffer,LPVOID* ppImageBuffer)
{
	PIMAGE_DOS_HEADER pDosHeader=NULL;
	PIMAGE_NT_HEADERS pNTHeader=NULL;
	PIMAGE_FILE_HEADER pFileHeader=NULL;
	PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL;
	PIMAGE_SECTION_HEADER pSectionHeader=NULL;

	if(!pFileBuffer)
	{
		printf("FileBuffer函数调用失败\n");
		return 0;
	}
	printf("%x\n",pFileBuffer);
//判断是否是PE文件
	pDosHeader=(PIMAGE_DOS_HEADER)pFileBuffer;
	if(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ标志\n");
		return 0;
	}

	pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
	if(pNTHeader->Signature!=IMAGE_NT_SIGNATURE)
	{
		printf("不是有效的PE标志\n");
		return 0;
	}

	pFileHeader=(PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
	
	pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader+20);


	//开辟ImageBuffer空间
	*ppImageBuffer=malloc(pOptionalHeader->SizeOfImage);
	if(!*ppImageBuffer)
	{
		printf("开辟ImageBuffer空间失败");
		return 0;
	}
	printf("SizeOfImage%x\n",pOptionalHeader->SizeOfImage);
	//malloc清零
	memset(*ppImageBuffer,0,pOptionalHeader->SizeOfImage);

	//复制Headers
	printf("SizeOfHeader%x\n",pOptionalHeader->SizeOfHeaders);
	memcpy(*ppImageBuffer,pDosHeader,pOptionalHeader->SizeOfHeaders);

	//循环复制节表
	pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
	for(int i=1;i<=pFileHeader->NumberOfSections;i++,pSectionHeader++)
	{
		memcpy((LPVOID)((DWORD)*ppImageBuffer+pSectionHeader->VirtualAddress),(LPVOID)((DWORD)pFileBuffer+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData);
		printf("%d\n",i);
	}
	printf("拷贝完成\n");
	return pOptionalHeader->SizeOfImage;
}




/
//ImageBufferToFileBuffer
DWORD ImageBufferToFileBuffer(LPVOID pImageBuffer,LPVOID* ppBuffer)
{
	PIMAGE_DOS_HEADER pDosHeader=NULL;
	PIMAGE_NT_HEADERS pNTHeader=NULL;
	PIMAGE_FILE_HEADER pFileHeader=NULL;
	PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL;
	PIMAGE_SECTION_HEADER pSectionHeader=NULL;

	if(!pImageBuffer)
	{
		printf("error");
		return 0;
	}

	pDosHeader=(PIMAGE_DOS_HEADER)pImageBuffer;
	pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pImageBuffer+pDosHeader->e_lfanew);
	pFileHeader=(PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
	pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + 20);
	pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);

	//得到FileBuffer的大小
	for(int i=1;i<pFileHeader->NumberOfSections;i++,pSectionHeader++)
	{
		printf("%d\n",i);
	}
	
	//循环到最后一个节表
	DWORD SizeOfBuffer=pSectionHeader->PointerToRawData+pSectionHeader->SizeOfRawData;

	//开辟空间
	*ppBuffer=malloc(SizeOfBuffer);
	if(!*ppBuffer)
	{
		printf("开辟Buffer空间失败\n");
		return 0;
	}
	printf("SizeOfBuffer%x\n",SizeOfBuffer);
	memset(*ppBuffer,0,SizeOfBuffer);

	//复制头
	memcpy(*ppBuffer,pImageBuffer,pOptionalHeader->SizeOfHeaders);
	//复制节表
	pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
	for(int j=1;j<=pFileHeader->NumberOfSections;j++,pSectionHeader++)
	{
		printf("%d\n",j);
		memcpy((LPVOID)((DWORD)*ppBuffer+pSectionHeader->PointerToRawData),(LPVOID)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress),pSectionHeader->SizeOfRawData);
	}
	printf("拷贝完成\n");
	return SizeOfBuffer;


}





/
//存贮到新的exe
BOOL MemeryToFile(LPVOID pBuffer,DWORD SizeOfBuffer)
{
	FILE* fpw=fopen("C://WINDOWS//system32//creakme.exe","wb");
	if(!fpw)
	{
		printf("fpw error");
		return false;
	}
	if (fwrite(pBuffer, 1, SizeOfBuffer, fpw) == 0)
	{
		printf("fpw fwrite fail");
		return false;
	}
	fclose(fpw);			
	fpw = NULL;
	printf("success\n");
	return true;

}








int main()
{
	LPVOID pFileBuffer=NULL;
	LPVOID* ppFileBuffer=&pFileBuffer;    //定义二级指针
	LPVOID pImageBuffer=NULL;
	LPVOID* ppImageBuffer=&pImageBuffer;  //定义二级指针
	DWORD SizeOfFileBuffer=0;
	DWORD SizeOfImageBuffer=0;
	DWORD SizeOfBuffer=0;

	LPVOID pBuffer=NULL;
	LPVOID* ppBuffer=&pBuffer;


	//调用filebuffer函数
	SizeOfFileBuffer=ReadPEFile(ppFileBuffer);
	if(!SizeOfFileBuffer)
	{
		printf("FileBuffer函数调用失败 \n");
		return 0;
	}
	pFileBuffer=*ppFileBuffer;



	//调用FileBufferToImageBuffer函数
	SizeOfBuffer=FileBufferToImageBuffer(pFileBuffer,ppImageBuffer);

	if(!SizeOfBuffer)
	{
		printf("调用FileBufferToImageBuffer函数失败");
		return 0;
	}

	//调用ImageBufferToBuffer
	SizeOfBuffer=ImageBufferToFileBuffer(pImageBuffer,ppBuffer);
	pBuffer=*ppBuffer;
	if(!SizeOfBuffer)
	{
		printf("SizeOfBuffer error");
		return 0;
	}

	//调用MemeryToFile
	if(MemeryToFile(pBuffer,SizeOfBuffer)==false)
	{
		printf("end");
		return 0;
	}





}

代码效果:

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,可以通过以下步骤在 Antd Vue 的 Table 列表中实现点击预览 XLSX 文件弹窗: 1. 安装 `file-saver` 和 `xlsx` 库 ``` npm install file-saver xlsx --save ``` 2. 在 Table 组件中添加一个列,用于显示预览按钮 ```vue <template> <a-table :dataSource="dataSource" :columns="columns"> <template #action="text, record"> <a @click="previewExcel(record)">预览</a> </template> </a-table> </template> <script> import { saveAs } from 'file-saver'; import XLSX from 'xlsx'; export default { data() { return { dataSource: [{ name: 'John', age: 32 }, { name: 'Bob', age: 24 }], columns: [ { title: 'Name', dataIndex: 'name', key: 'name', }, { title: 'Age', dataIndex: 'age', key: 'age', }, { title: 'Action', key: 'action', slots: { customRender: 'action' }, }, ], }; }, methods: { previewExcel(record) { const worksheet = XLSX.utils.json_to_sheet([record]); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); const fileBuffer = XLSX.write(workbook, { type: 'array', bookType: 'xlsx' }); const blob = new Blob([fileBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); saveAs(blob, `preview-${record.name}.xlsx`); }, }, }; </script> ``` 在上面的代码中,我们添加了一个 `action` 列,用于显示预览按钮。在 `previewExcel` 方法中,我们将当前行的数据转换为 XLSX 文件,并将其保存为 Blob 对象,然后使用 `file-saver` 库的 `saveAs` 方法将该 Blob 对象保存为文件并下载。 注意,这里我们使用的是 `json_to_sheet` 方法将数据转换为 XLSX 文件,只会将第一个数据对象转换为 XLSX 文件。如果需要将整个列表转换为 XLSX 文件,可以使用 `json_to_sheet` 方法将整个数据源转换为 XLSX 文件,然后使用 `book_append_sheet` 方法将该表添加到工作簿中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值