滴水三期:day34.1-扩大节、合并节

滴水三期:day01.1-初识逆向 一、机制与0,1>二、PE文件结构>三、硬编码>四、逆向的过程>五、初级阶段需要完成的项目 阅读详情

一、添加代码的方式

  • 我们现在学过的有:①直接在任意节的空白区添加代码;②新增节添加代码;③扩大最后一个节添加代码
  • 今天要学习:④合并节并添加代码

二、合并节思路

  • 使用拉伸后的合并更方便计算节合并后的大小,而且可以保证计算的正确性。如果用FileBuffer算,算地址或者大小时还要担心节中未初始化数据在拉伸后导致节变大等等情况。

  • 合并节就是:把第一个节开始一直到最后一个节的结尾都当成第一个节

  • 但是可能会造成合并后文件变大,因为文件对齐粒度一般都要小于内存对齐粒度,所以虚拟内存中每个节的空白区一般比文件空白区要大一些,现在合并节是把虚拟内存中从第一个节开始到文件结束都当成一个节,最后再变成FileBuffer就会变大。

  • 步骤:

    1. NumberOfSections改成1

    2. 修改第一个节表的字段

      • VirtualSize:
        • 方法一:SizeOfImage - 第一个节VirtualAddress
        • 方法二:还可以通过最后一个节的VirtualAddress + 最后一个节的VirtualSize内存对齐后的大小 - SizeOfHeader内存对齐后的大小
      • SizeOfRawData:等于VirtualSize即可
    3. 将第一个节的属性改为包含所有节的属性,即用第一个节的属性与其他的节的属性做或运算

三、作业

1.扩大最后一个节,保证程序正常运行(手动)

day33.1中写过用编程实现扩大节,所以今天再试着用手动的方式体会一下扩大节,由于手动的时候是在FileBuffer中操作,所以有些值的计算包括扩大的大小都是需要计算的,没有在ImageBuffer中扩大节那么方便

  • 打开notepad.exe程序,如果我们想扩大0x1000字节,则需要修改SizeOfImage,0x13000 + 0x1000内存对齐后 = 0x14000(我们知道notepad.exe的内存对齐为0x1000;文件对齐为0x200)

    image-20211231114041243
  • 接着找到最后一个节表,修改VirtualSize = 原来的0x8948内存对齐后0x9000 + 0x1000内存对齐后 = 0xA000

  • SizeOfRawData = VirtualSize即可

  • 最后将最后一个节的属性0x40000040与0x60000020亦或得到0x60000060

    image-20211231114508991
  • 最后最关键的一步就是在最后一个节末尾扩大节,我们知道如果在ImageBuffer中扩大节,就直接在末尾加上0x1000字节即可,但是由于现在是在FileBuffer中操作,不能直接扩大0x1000了,不然就跟SizeOfRawData对不上,我们要通过计算来得到:原来的SizeOfRawData为0x8A00,而扩大后的SizeOfRawData = 0xA000,所以只需要扩大0xA000 - 0x8A00 = 0x1600即可,换算成十进制为5632。所以在文件末尾0x101FF处右键–Edit–Paste Zero Bytes–输入5632

    image-20211231115647352
  • 保存运行,再拖入PEtool中查看是否修改成功

    image-20211231114651836

2.编码实现合并节

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>

typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned char BYTE;

#define MZ 0x5A4D
#define PE 0x4550
#define IMAGE_SIZEOF_SHORT_NAME 8
#define MessageBox_Address 0x77D36476 //宏定义记事本的MessageBox内存地址

//shellcode
BYTE shellcode[] = {
	0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00,
	0xE8,0x00,0x00,0x00,0x00,
	0xE9,0x00,0x00,0x00,0x00
};

//DOS头
struct _IMAGE_DOS_HEADER {
	WORD e_magic;  //MZ标记
	WORD e_cblp;
	WORD e_cp;
	WORD e_crlc;
	WORD e_cparhdr;
	WORD e_minalloc;
	WORD e_maxalloc;
	WORD e_ss;
	WORD e_sp;
	WORD e_csum;
	WORD e_ip;
	WORD e_cs;
	WORD e_lfarlc;
	WORD e_ovno;
	WORD e_res[4];
	WORD e_oemid;
	WORD e_oeminfo;
	WORD e_res2[10];
	DWORD e_lfanew;  //PE文件真正开始的偏移地址
};

//标准PE头
struct _IMAGE_FILE_HEADER {
	WORD Machine;  //文件运行平台
	WORD NumberOfSections;  //节数量
	DWORD TimeDateStamp;  //时间戳
	DWORD PointerToSymbolTable;
	DWORD NumberOfSymbols;
	WORD SizeOfOptionalHeader;  //可选PE头大小
	WORD Characteristics;  //特征值
};

//可选PE头
struct _IMAGE_OPTIONAL_HEADER {
	WORD Magic;  //文件类型
	BYTE MajorLinkerVersion;
	BYTE MinorLinkerVersion;
	DWORD SizeOfCode;   //代码节文件对齐后的大小
	DWORD SizeOfInitializedData;  //初始化数据文件对齐后的大小
	DWORD SizeOfUninitializedData;  //未初始化数据文件对齐后大小
	DWORD AddressOfEntryPoint;  //程序入口点(偏移量)
	DWORD BaseOfCode;  //代码基址
	DWORD BaseOfData;  //数据基址
	DWORD ImageBase;   //内存镜像基址
	DWORD SectionAlignment;  //内存对齐粒度
	DWORD FileAlignment;  //文件对齐粒度
	WORD MajorOperatingSystemVersion;
	WORD MinorOperatingSystemVersion;
	WORD MajorImageVersion;
	WORD MinorImageVersion;
	WORD MajorSubsystemVersion;
	WORD MinorSubsystemVersion;
	DWORD Win32VersionValue;
	DWORD SizeOfImage;  //文件装入虚拟内存后大小
	DWORD SizeOfHeaders;  //DOS、NT头和节表大小
	DWORD CheckSum;  //校验和
	WORD Subsystem;
	WORD DllCharacteristics;
	DWORD SizeOfStackReserve;  //预留堆栈大小
	DWORD SizeOfStackCommit;  //实际分配堆栈大小
	DWORD SizeOfHeapReserve;  //预留堆大小
	DWORD SizeOfHeapCommit;  //实际分配堆大小
	DWORD LoaderFlags;
	DWORD NumberOfRvaAndSizes;  //目录项数目
	//_IMAGE_DATA_DIRECTORY DataDirectory[16];  //这个先不管
};

//NT头
struct _IMAGE_NT_HEADERS {
	DWORD Signature;  //PE签名
	_IMAGE_FILE_HEADER FileHeader;
	_IMAGE_OPTIONAL_HEADER OptionalHeader;
};

//节表
struct _IMAGE_SECTION_HEADER{
	BYTE Name[IMAGE_SIZEOF_SHORT_NAME];  //节表名
	union{
		DWORD PhysicalAddress;
		DWORD VirtualSize;  //内存中未对齐大小
	}Misc;
	DWORD VirtualAddress;  //该节在内存中偏移地址
	DWORD SizeOfRawData;  //该节在硬盘上文件对齐后大小
	DWORD PointerToRawData;  //该节在硬盘上文件对齐后偏移地址
	DWORD PointerToRelocations;
	DWORD PointerToLinenumbers;
	WORD NumberOfRelocations;
	WORD NumberOfLinenumbers;
	DWORD Characteristics;  //该节特征属性
};

/*计算文件大小函数
参数:文件绝对路径
返回值:返回文件大小(单位字节)
*/
int compute_file_size(char* filePath){
	FILE* fp = fopen(filePath,"rb");
    if(!fp){
		printf("打开文件失败");
		exit(0);
	}
    fseek(fp,0,2);
	int size = ftell(fp);
	//fseek(fp,0,0); 单纯计算文件大小,就不需要还原指针了
	fclose(fp);
	return size;
}

/*将文件读入FileBuffer函数
参数:文件绝对路径
返回值:FileBuffer起始地址
*/
char* to_FileBuffer(char* filePath){
    FILE* fp = fopen(filePath,"rb");
    if(!fp){
		printf("打开文件失败");
		exit(0);
	}
    int size = compute_file_size(filePath);
    
	char* mp = (char*)malloc(sizeof(char) * size);  //分配内存空间
    if(!mp){
        printf("分配空间失败");
        fclose(fp);
        exit(0);
    }
    
    int isSucceed = fread(mp,size,1,fp);
    if(!isSucceed){
        printf("读取数据失败");
        free(mp);
        fclose(fp);
        exit(0);
    }
    
    fclose(fp);
    return mp;
}

/*FileBuffer到ImageBuffer函数
参数:FileBuffer起始地址
返回值:ImageBuffer起始地址
*/
char* fileBuffer_to_ImageBuffer(char* fileBufferp){

	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_SECTION_HEADER* _image_section_header = NULL;

	_image_dos_header = (_IMAGE_DOS_HEADER*)fileBufferp;
	_image_file_header = (_IMAGE_FILE_HEADER*)(fileBufferp + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_section_header = (_IMAGE_SECTION_HEADER*)((char*)_image_optional_header + _image_file_header->SizeOfOptionalHeader);

	DWORD sizeofImage = _image_optional_header->SizeOfImage;
	char* imageBufferp = (char*)malloc(sizeofImage);
	if(NULL == imageBufferp){
        printf("动态申请ImageBuffer内存失败\n");
        exit(0);
    }
	for(DWORD i = 0;i < sizeofImage;i++){
		*(imageBufferp + i) = 0x00;
	}

	//strncpy(imageBufferp,fileBufferp,_image_optional_header->SizeOfHeaders); 因为imageBufferp,fileBufferp值会变,所以这个方法不太好
	for(i = 0;i < _image_optional_header->SizeOfHeaders;i++){
		*(imageBufferp + i) = *(fileBufferp + i);
	}
	

	for(i = 0;i < _image_file_header->NumberOfSections;i++){
		for(DWORD j = 0;j < _image_section_header->SizeOfRawData;j++){
			*(imageBufferp + _image_section_header->VirtualAddress + j) = *(fileBufferp + 
				_image_section_header->PointerToRawData + j);
		}
		_image_section_header++;
	}

	return imageBufferp;
}

/*计算NewBuffer大小函数
参数:NewBuffer起始地址
返回值:unsigned int类型(单位:字节)
*/
DWORD compute_NewBuffer_size(char* newBufferp){
	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_SECTION_HEADER* _image_section_header = NULL;

	_image_dos_header = (_IMAGE_DOS_HEADER*)newBufferp;
	_image_file_header = (_IMAGE_FILE_HEADER*)(newBufferp + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_section_header = (_IMAGE_SECTION_HEADER*)((char*)_image_optional_header + _image_file_header->SizeOfOptionalHeader);
	
	_IMAGE_SECTION_HEADER* last_image_section_header = _image_section_header + _image_file_header->NumberOfSections - 1;
	DWORD sizeofNewBuffer = last_image_section_header->PointerToRawData + last_image_section_header->SizeOfRawData;
	return sizeofNewBuffer;
}

/*ImageBuffer到NewBuffer函数
参数:ImageBuffer起始地址
返回值:NewBuffer起始地址
*/
char* imageBuffer_to_NewBuffer(char* imageBufferp){
	
	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_SECTION_HEADER* _image_section_header = NULL;

	_image_dos_header = (_IMAGE_DOS_HEADER*)imageBufferp;
	_image_file_header = (_IMAGE_FILE_HEADER*)(imageBufferp + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_section_header = (_IMAGE_SECTION_HEADER*)((char*)_image_optional_header + _image_file_header->SizeOfOptionalHeader);

	//重新计算newBuffer需要大小
	/*方法一:SizeOfHEADER + 所有节的SizeOfRawData之和
	int sizeofSections = 0;  
	_IMAGE_SECTION_HEADER* _image_section_header_temp = _image_section_header;
	for(DWORD i = 0;i < _image_file_header->NumberOfSections;i++){
		sizeofSections += _image_section_header_temp->SizeOfRawData;
		_image_section_header_temp++;
	}
	char* newBufferp = (char*)malloc(_image_optional_header->SizeOfHeaders + sizeofSections);
	*/
	
	//方法二:使用最后一个节的文件偏移地址 + 最后一个节对齐后的大小
	DWORD size = compute_NewBuffer_size(imageBufferp);
	char* newBufferp = (char*)malloc(size);
	if(NULL == newBufferp){
        printf("NewBuffer内存分配失败\n");
        exit(0);
    }
	for(DWORD i = 0;i < size;i++){
		*(newBufferp + i) = 0x00;
	}
	
	
	for(i = 0;i < _image_optional_header->SizeOfHeaders;i++){
		*(newBufferp + i) = *(imageBufferp + i);
	}
	
	for(i = 0;i < _image_file_header->NumberOfSections;i++){
		for(DWORD j = 0;j < _image_section_header->SizeOfRawData;j++){ //不用VirtualSize因为害怕会多复制覆盖下一个节
			*(newBufferp + _image_section_header->PointerToRawData + j) = *(imageBufferp + 
				_image_section_header->VirtualAddress + j);
		}
		_image_section_header++;
	}

	return newBufferp;
}	

/*NewBuffer存盘函数
参数:需要写出数据的内存首地址,保存绝对路径,写出的数据大小(单位:字节)
返回值:成功返回1,失败返回0
*/
int save_to_disk(char* newBufferp,char* storagePath,DWORD size){
	FILE* fp = fopen(storagePath,"wb");
	if(!fp){
		printf("打开文件失败");
		return 0;
	}
	int isSucceed = fwrite(newBufferp,size,1,fp);
	if(!isSucceed){
        free(newBufferp);
        fclose(fp);
        return 0;
    }
	fclose(fp);
	return 1;
}

/*合并节函数
参数:需要合并节的可执行文件ImageBuffer起始地址
返回值:合并后的ImageBuffer起始地址(因为合并节后并不改变ImageBuffer内存大小,所以返回void也行)
*/
char* merge_section(char* imageBufferp){
	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_SECTION_HEADER* _image_section_header = NULL;

	_image_dos_header = (_IMAGE_DOS_HEADER*)imageBufferp;
	_image_file_header = (_IMAGE_FILE_HEADER*)(imageBufferp + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_section_header = (_IMAGE_SECTION_HEADER*)((char*)_image_optional_header + _image_file_header->SizeOfOptionalHeader);
	
	//修改合并节的节表字段
	_image_section_header->Misc.VirtualSize = _image_optional_header->SizeOfImage - _image_section_header->VirtualAddress;
	_image_section_header->SizeOfRawData = _image_section_header->Misc.VirtualSize;
	for(int i = 1;i < _image_file_header->NumberOfSections;i++){
		_image_section_header->Characteristics = _image_section_header->Characteristics | (_image_section_header + i)->Characteristics;
	}

	/*前面提到过节表末尾应该跟40个0x00,但是如果修改了,文件就打不开了?不知道原因是啥
	for(i = 0;i < 40 * _image_file_header->NumberOfSections;i++){
		*((char*)(_image_section_header + 1) + i) = 0x00;
	}*/
	
	//修改NumberOfSections字段
	_image_file_header->NumberOfSections = 1;
	
	return imageBufferp;
}

int main(int argc,char* argv[]){
    char* filePath = "D:/C-language/file/notepad.exe";  //你要打开的PE文件绝对路径
    char* storagePath = "D:/C-language/file/notepad_merge.exe"; //保存路径

	//char* filePath = "D:/IPMsg/ipmsg.exe";  //你要打开的PE文件绝对路径
    //char* storagePath = "D:/IPMsg/ipmsg_merge.exe"; //保存路径

	char* fileBufferp = to_FileBuffer(filePath);
	char* imageBufferp = fileBuffer_to_ImageBuffer(fileBufferp);
	imageBufferp = merge_section(imageBufferp);

	char* newBufferp = imageBuffer_to_NewBuffer(imageBufferp);
	DWORD size = compute_NewBuffer_size(newBufferp);
	int isSucceed = save_to_disk(newBufferp,storagePath,size);
	if(!isSucceed){
		printf("存盘失败");
    	getchar();
    }else
		printf("存盘成功");
	
	free(fileBufferp);
	free(imageBufferp);
	free(newBufferp);

	return 0;
}

3.定义函数,能够返回对齐后的大小

  • 说明:定义一个函数Align(int x,int y),第一个参数为我们手动输入的字节大小,第二个参数为文件对齐大小或者内存对齐大小,现在功能是如果我们传入0x222字节,文件对齐大小为0x200,那么计算0x222文件对齐后的大小为多少;如果传入0x1222字节,内存对齐大小为0x1000,那么计算0x1222内存对齐后的大小是多少

  • 代码如下:

    #include "stdafx.h"
    typedef unsigned int DWORD; //因为一般alignment函数都是用于PE结构字段,都是无符号整形
    
    /*计算一个数按照某对齐粒度对齐后的值函数
    参数:一个数,对齐粒度
    返回值:此数对齐后的值,返回0表示参数不合法
    */
    DWORD alignment(DWORD num,DWORD align_num){  //用int也行
        if((int)num <= 0 || (int)align_num <= 0){
            printf("输入的数据不合法\n");
            return 0;
        }
    	if(num % align_num == 0){
    		return num;
    	}else{
    		return align_num * (num / align_num + 1);
    	}
    }
    int main(int argc,char* argv[]){
    	printf("%x",alignment(0x3700,0x1000)); //0x4000
    	return 0;
    }
    
滴水逆向——PE合并节 1.问题描述: 2.代码实现: #include<stdio.h> #include<stdlib.h> #include<windows.h> #define size_shellcode 0x12 #define size_surplus_sizeofheader 0x50 #define messagebox_add 0x76EE2030 ... 阅读详情

相关推荐

滴水三期完整版(96课时)

第1讲:2015-01-12(进制01) 第2讲:2015-01-13(进制02) 第3讲:2015-01-14(数据宽度-逻辑运算03) 第4讲:2015-01-15(通用寄存器-内存读写04) 第5讲:2015-01-16(内存寻址-堆栈05) 第6讲:2015-01-19(EFLAGS寄存器06) 第7讲:2015-01-20(JCC) 第8讲:2015-01-21(堆栈图) 第8讲:2015-01-21(宝马问题) 第9讲:2015-01-22(堆栈图2) 第10讲:2015-01-23(C语言01_后半段) 第10讲:2015-01-23(C语言完整版) 第11讲:2015-01-26(C语言02_数据类型) 第12讲:2015-01-27(C语言03_数据类型_IF语句) 第13讲:2015-01-28(C语言04_IF语句逆向分析上) 第14讲:2015-01-28(C语言04_IF语句逆向分析下) 第15讲:2015-01-29(C语言04_正向基础) 第16讲:2015-01-30(C语言05_循环语句) 第17讲:2015-02-02(C语言06_参数_返回值_局部变量_数组反汇编) 第18讲:2015-02-02(2015-01-30课后练习) 第19讲:2015-02-03(C语言07_多维数组) 第20讲:2015-02-03(2015-02-02课后练习) 第21讲:2015-02-04(C语言08_结构体) 第22讲:2015-02-05(C语言09_字节对齐_结构体数组) 第23讲:2015-02-06(C语言10_Switch语句反汇编) 第24讲:2015-02-26(C语言11_指针1) 第25讲:2015-02-27(C语言11_指针2) 第26讲:2015-02-28(C语言11_指针3) 第27讲:2015-02-28(C语言11_指针4) 第28讲:2015-03-02(C语言11_指针5) 第29讲:2015-03-03(C语言11_指针6) 第30讲:2015-03-04(C语言11_指针7) 第31讲:2015-03-06(C语言11_指针8) 第32讲:2015-03-09(位运算) 第33讲:2015-03-10(内存分配_文件读写) 第34讲:2015-03-11(PE头解析_手动) 第35讲:2015-03-12(PE头字段说明) 第36讲:2015-03-13(PE节表) 第37讲:2015-03-16(FileBuffer转ImageBuffer) 第38讲:2015-03-17(代码节空白区添加代码) 第39讲:2015-03-18(任意节空白区添加代码) 第40讲:2015-03-19(新增节添加代码) 第41讲:2015-03-20(扩大节-合并节-数据目录) 第42讲:2015-03-23(静态连接库-动态链接库) 第43讲:2015-03-24(导出表) 第44讲:2015-03-25(重定位表) 第45讲:2015-03-26(移动导出表-重定位表) 第46讲:2015-03-27(IAT表) 第47讲:2015-03-27(导入表) 第48讲:2015-03-30(绑定导入表) 第49讲:2015-03-31(导入表注入) 第50讲:2015-04-01(C++ this指针 类 上) 第51讲:2015-04-01(C++ this指针 类 下) 第52讲:2015-04-02(C++ 构造-析构函数 继承) 第53讲:2015-04-03(C++ 权限控制) 第54讲:2015-04-07(C++ 虚函数表) 第55讲:2015-04-08(C++ 动态绑定-多态-上) 第56讲:2015-04-08(C++ 动态绑定-多态-下) 第57讲:2015-04-09(C++ 模版) 第58讲:2015-04-10(C++ 引用-友元-运算符重载) 第59讲:2015-04-13(C++ new-delete-Vector) 第60讲:2015-04-14(C++Vector实现) 第61讲:2015-04-15(C++链表) 第62讲:2015-04-16(C++链表实现) 第63讲:2015-04-16(C++二叉树) 第64讲:2015-04-17(C++二叉树实现) 第65讲:2015-04-20(Win32 宽字符) 第66讲:2015-04-21(Win32 事件-消息-消息处理函数) 第67讲:2015-04-22(Win32 ESP寻址-定位回调函数-条件断点) 第68讲:2015-04-23(Win32 子窗口-消息处理函数定位) 第69讲:2015-04-24(Win32 资源文件-消息断点) 第70讲:2015-04-27(Win32 提取图标-修改标题) 第71讲:2015-04-28(Win32 通用控件-VM_NOTIFY) 第72讲:2015-04-29(Win32 PE查看器-项目要求) 项目一:PE查看器 开发周期(5天) 需求文档 第73讲:2015-05-07(Win32 创建线程) 第74讲:2015-05-08(Win32 线程控制_CONTEXT) 第75讲:2015-05-11(Win32 临界区) 第76讲:2015-05-12(Win32 互斥体) 第77讲:2015-05-13(Win32 事件) 第78讲:2015-05-14(Win32 信号量) 第79讲:2015-05-15(Win32 线程同步与线程互斥) 第80讲:2015-05-18(Win32 进程创建_句柄表) 第81讲:2015-05-20(Win32 以挂起形式创建进程) 第82讲:2015-05-21(Win32 加密壳_项目说明) 项目二:加密壳 开发周期(5天) 需求文档 第83讲:2015-05-28(Win32 枚举窗口_鼠标键盘事件) 第84讲:2015-05-29(Win32 CE练习) 第85讲:2015-06-01(Win32 OD练习) 第86讲:2015-06-03(Win32 ShellCode_远程线程注入) 第87讲:2015-06-04(Win32 加载EXE_模块隐藏) 第88讲:2015-06-09(Win32 IAT_HOOK) 第89讲:2015-06-10(Win32 InlineHook) 第90讲:2015-06-11(Win32 进程通信) 第91讲:2015-06-11(Win32 进程监控_项目说明) 项目三:进程监控 开发周期(5天) 需求文档 第92讲:2015-06-15(硬编码_01) 第93讲:2015-06-16(硬编码_02) 第94讲:2015-06-17(硬编码_03) 第95讲:2015-06-18(硬编码_04) 第96讲:2015-06-19(硬编码_05)

10.PE文件之合并节

目录 合并节对PE文件中哪些值会有影响? 合并节步骤: 手动合并节 代码合并节 合并节与新增节、扩大节有一点区别.合并节如果文件与内存对齐不同需拉伸到内存后进行合并节. 合并节对PE文件中哪些值会有影响? IMAGE_FILE_HEADER→NumberOfSections(当前PE文件节的数量,如果更改需要修正此值). .第一个节得包含其余所有节的属性. 修正第一个节内存中的大小以及文件中的大小. 如果文件对齐与内存对齐相等则不需要拉伸即可完成.如果文件对齐与内存对齐不相同必须拉伸

kernelhack 4260

滴水逆向3期初级和中级课件(海东老师讲)

滴水逆向3期初级和中级课件(海东老师讲) 全套包括 EXE 练手文件 配套电子书......

滴水逆向三期实践7:合并节

会不会有极端情况,DOS stub的空间也不足,NT头和节表不能抬升,节表和第一节之间也没有空隙插入新节,这种情况如何加入自己的代码呢? 就需要到合并节,将全部的节(一般文件都有两个以上的节)合并成一个节,那就可以有空隙增加自己的节表了。这里不搞那么复杂了,只做合并节,将全部节合并成一个后文件仍然可用即可。 合并节: 1、拉伸到内存 (这里是真的拉伸到一块内存空间) 2、将第一个节的内存大小、文件大小改成一样 VirtualSize =...

Rivival_S 的博客 980

滴水逆向3期作业Filebuffer->Imagebuffer->Newbuffer->存盘功能C++源码

滴水逆向3期作业——filebuffer->imagebuffer->newbuffer->存盘功能源码,了解对文件的PE头解析等原理等,代码容易理解,注释丰富,是学习PE的好帮手!

若依ruoyi框架实现单点登录或者接入统一认证

log.info("单点登录用户[{}]不存在, 需要创建.", loginName);log.info("单点登录用户[{}]已存在.", loginName);jsonObjectData.put("nickName","单点1");if (code.equals("0")) {//验证成功需要自动登录。jsonObject.put("msg","验证成功");ajax.put("msg", "登录成功");

GitHub质检员 2万+

PE_合并节

PE

qq_42363151的博客 428

【Vite+Vue3+TS】基于Vite+Vue3+TypeScript+ESLint+Prettier+Stylelint搭建项目(亲测超详细)

结合了很多项目和文章,总结一篇项目构建的笔记。 温馨提示:文章末尾记录了我在搭建项目过程中,遇到的一些问题和解决办法 ~

aDiaoYa_的博客 4231

PE知识复习之PE合并节

                      PE知识复习之PE合并节 一丶简介    根据上一讲.我们为PE新增了一个节. 并且属性了各个成员中的相互配合. 例如文件头记录节个数.我们新增节就要修改这个个数. 那么现在我们要合并一个节.以上一讲我们例子讲解.   以前我们讲过PE扩大一个节怎么做. 合并节跟扩大节类似. 只不过一个是扩大. 一个是合并了. 合并节的步骤.   1.修改文...

weixin_30794851的博客 487

强化学习-----DQN(Deep Q-network)

DQN(Deep Q-Network)是一种基于深度学习和强化学习的算法,由DeepMind提出,用于解决离散动作空间下的马尔科夫决策过程(MDP)问题。它是首个成功将深度学习应用于解决强化学习任务的算法之一。DQN,即深度Q网络(Deep Q-network),是指基于深度学习的Q-Learing算法。那什么是Q-leaning?可以看上一篇文章Q-learning是一种经典的强化学习算法,用于解决马尔可夫决策过程(Markov Decision Process,MDP)中的控制问题。

qq_74722169的博客 2万+

从TCGA官网获取新版count数据并精准转换为TPM的实战指南

本文详细介绍了从TCGA官网获取新版count数据并精准转换为TPM的实战指南。通过TCGAbiolinks工具下载原始count数据,结合GENCODE v36注释文件计算基因有效长度,最终实现count到TPM的标准化转换,确保数据完整性和分析可靠性。文章包含完整代码示例和常见问题解决方案,特别适合生物信息学研究人员参考。

weixin_27310417的博客 283

博客摘录「 滴水三期:day34.1-扩大节、合并节」2024年3月8日

合并节函数参数:需要合并节的可执行文件ImageBuffer起始地址返回值:合并后的ImageBuffer起始地址(因为合并节后并不改变ImageBuffer内存大小,所以返回void也行)

DeMaJIKA的博客 149

微信删除的聊天记录怎么恢复(2024年最新攻略合集)

随着微信对我们生活中方方面面的渗透,微信已然从一款简单的社交软件过渡成为现时代的一种生活方式,而微信中的聊天记录就是我们和朋友之间历程的最好证明。对此,今天我们来聊聊微信删除的聊天记录怎么恢复的问题。

m0_70960708的博客 945

滴水逆向三期笔记和作业-PE总结1

PE头手动解析,节表,FileBuffer-ImageBuffer

weixin_44449397的博客 3304

《手把手教你YOLOv9实战》,改进专栏目录

为了提供友好的操作效果,本专栏将会手把手搭建可视化界面,我将用PyQt5 搭建一个可视化界面,可视化界面能够实现基本的图像加载与检测功能,如支持视频、摄像头,还支持更换不同的 YOLOv9 模型,并适应不同领域(如口罩检测系统、人脸检测系统、工业缺陷检测系统等),界面灵活、功能强大。通过YOLOv9加以改进设计,形成新的算法框架,一起水科研和论文,专栏会一直持续更新中,本专栏适合目标检测、分割、分类。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 2155

YOLO11改进|注意力机制篇|引入ELA注意力机制

YOLO11添加ELA注意力机制

A1983Z的博客 3647

扩大节-合并节

注意:扩大节最好在最后节扩展 不然要修改好多东西一:扩大节1、拉伸到内存2、分配一块新的空间:SizeOfImage+Ex3、将最后一个节的SizeOfRawData 和 VirtualSize改成NN = (SizeOfRawData或者Virtualsize 内存对齐后的值)+Ex4、修改sizeofimage大小。

qq_51600802的博客 304

【保姆级教程】教你如何轻松获取MIMIC数据使用权限

文章非常详细地介绍了MIMIC数据库申请使用的全部步骤。

越努力 越幸运 6599

PE文件(五)数据目录

添加shellcode有以下几种的方式:1.直接在任意节的空白区添加代码2.新增节添加代码3.扩大最后一个节添加代码4.合并节并添加代码今天我们学习如何扩大节,合并节扩大节在上一节的学习中,我们可以通过上移NT头和节表覆盖DOS Stub以获取足够的空白区来增加新的节表以及后续新增节,但是当整体上移覆盖DOS Stub之后,多出来的空白区域还不够新增节表时,我们就可以使用扩大最后一个节的方法来添加我们的shellcode扩大节主要用于当我们在。

2301_78838647的博客 1514

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

2021-04-06 函数的参数是如何入栈出栈的

函数的参数是如何入栈出栈的 制作逆向靶 建议用debug版而不是release版,因为release版会自作聪明把很多东西省略掉 在调试器中 寄存器EIP 表示当前程序走到哪一步了 ctrl+G 光标定位到某一地址 在单步调试中 右侧哪个寄存器变红了 就是哪个寄存器发生了变化 call 的第一个作用就是 将EIP的值改为函数所在的地址 由硬编码知识 可以计算出返回地址的值,举例 E8 84 FF FF FF (call stack.00401005) 这行硬编码是5个字节 所以 call完的返

mfmfmmf1的专栏 231

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C语言实现PE的拉伸压缩和扩大、合并、增加节区

C语言实现PE的拉伸压缩和扩大、合并、增加节区 文章目录C语言实现PE的拉伸压缩和扩大、合并、增加节区0.说明一.各个部分的子函数1.读取2.拉伸3.压缩4.存盘5.扩大节6.合并节7.新增节二.整体代码 0.说明 看滴水初期视频PE部分的笔记 然后自己写代码实现 文件的拉伸过程 PE节区扩大、合并、增大都是在拉伸之后实现的 这之中涉及了许多结构体和自定义数据,都是定义在winnt.h这个头文件中,当然也被包含于windows.h这个头文件。开始的时候都是不熟,只有多写,自然就记着了。 编译环境:vc++

qq_35289660的博客 1947

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

9.PE文件之扩大节

目录 扩大节对PE文件中哪些值会有影响? 扩大节步骤: 手动扩大节 代码扩大节 通常扩大最后一个节比较方便,假设扩大第一个节则后续所有节对应的数据都需要更改. 扩大节对PE文件中哪些值会有影响? 最后一个IMAGE_SECTION_HEADER结构成员中SizeOfRawData和VirtualSize. IMAGE_OPTIONAL_HEADER → SizeOfImage(扩大节后在内存中的大小需要修正). 扩大节步骤: 将最后一个节文件中的大小修改为当前文件大小加新增大小(文

kernelhack 4043

PE实战教程之扩大节

本篇文章复习扩大节,顾名思义就是将节表的大小扩大,那就要搞清楚俩个问题: 1.为什么扩大节? 2.如何扩大节? PE实战教程之扩大节为什么扩大节如何扩大节?扩大哪一个节?扩大节的步骤实战环节: 为什么扩大节 上篇文章进行了空白区添加我们的代码,但是有的时候.我们的空白区不够了怎么办.所以需要进行扩大节。 如何扩大节? 我们先看节表的结构 typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //8个

weixin_43742894的博客 975

滴水逆向PE作业——扩大一个节

扩大一个节: 流程如下: 注意:修改完ImageBuffer后需要将其再压缩(拉伸的逆过程)后再存盘。 代码: // ExtendLastSection.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "windows.h" #include "malloc....

weixin_44584614的博客 933

滴水三期:day44.2-虚函数表

一、直接调用、间接调用 > 二、虚函数表反汇编分析(1.研究大小 > 2.虚函数表地址 > 3.调用虚函数的反汇编)三、作业(1.重载和重写 > 2.继承与虚函数表)

Edimade的博客 723

深挖C++:类和对象(中)

(先进后出)

xys_678的博客 239
上一篇: 滴水三期:day33.1-新增节、扩大节-添加代码
下一篇: 滴水三期:day34.2-数据目录
EdimadeZhou
博客等级 码龄5年 241粉丝 128原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值