当前位置:文档之家› 关于PE可执行文件的修改

关于PE可执行文件的修改

关于PE可执行文件的修改
关于PE可执行文件的修改

关于PE可执行文件的修改

原创:ilsy(ILSY)

在windows 9x、NT、2000下,所有的可执行文件都是基于Microsoft设计的一种新的文件格式Portable Executable File Format(可移植的执行体),即PE格式。有一些时候,我们需要对这些可执行文件进行修改,下面文字试图详细的描述PE文件的格式及对PE格式文件的修改。

1、PE文件框架构成

DOS MZ header

DOS stub

PE header

Section table

Section 1

Section 2

Section ...

Section n

上表是PE文件结构的总体层次分布。所有PE文件(甚至32位的DLLs) 必须以一个简单的DOS MZ header 开始,在偏移0处有DOS下可执行文件的“MZ标志”,有了它,一旦程序在DOS下执行,DOS就能识别出这是有效的执行体,然后运行紧随MZ header 之后的DOS stub。DOS stub实际上是个有效的EXE,在不支持PE文件格式的操作系统中,它将简单显示一个错误提示,类似于字符串" This program cannot run in DOS mode " 或者程序员可根据自己的意图实现完整的DOS代码。通常DOS stub由汇编器/编译器自动生成,对我们的用处不是很大,它简单调用中断21h服务9来显示字符串"This program cannot run in DOS mode"。

紧接着DOS stub 的是PE header。PE header 是PE相关结构IMAGE_NT_HEADERS 的简称,其中包含了许多PE装载器用到的重要域。可执行文件在支持PE文件结构的操作系统中执行时,PE装载器将从DOS MZ header的偏移3CH处找到PE header 的起始偏移量。因而跳过了DOS stub 直接定位到真正的文件头PE header。

PE文件的真正内容划分成块,称之为sections(节)。每节是一块拥有共同属性的数据,比如“.text”节等,那么,每一节的内容都是什么呢?实际上PE格式的文件把具有相同属性的内容放入同一个节中,而不必关心类似“.text”、“.data”的命名,其命名只是为了便于识别,所有,我们如果对PE格式的文件进行修改,理论上讲可以写入任何一个节内,并调整此节的属性就可以了。

PE header 接下来的数组结构section table(节表)。每个结构包含对应节的属性、文件偏移量、虚拟偏移量等。如果PE文件里有5个节,那么此结构数组内就有5个成员。

以上就是PE文件格式的物理分布,下面将总结一下装载一PE文件的主要步骤:

1、PE文件被执行,PE装载器检查DOS MZ header 里的PE header 偏移量。如果找到,则跳转到PE header。

2、PE装载器检查PE header 的有效性。如果有效,就跳转到PE header的尾部。

3、紧跟PE header 的是节表。PE装载器读取其中的节信息,并采用文件映射方法将这些节映射到内存,同时付上节表里指定的节属性。

4、PE文件映射入内存后,PE装载器将处理PE文件中类似import table(引入表)逻辑部分。

上述步骤是一些前辈分析的结果简述。

2、PE文件头概述

我们可以在winnt.h这个文件中找到关于PE文件头的定义:

typedef struct _IMAGE_NT_HEADERS {

DWORD Signature;

//PE文件头标志:“PE\0\0”。在开始DOS header的偏移3CH处所指向的地址开始IMAGE_FILE_HEADER FileHeader; //PE文件物理分布的信息

IMAGE_OPTIONAL_HEADER32 OptionalHeader; //PE文件逻辑分布的信息

} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

typedef struct _IMAGE_FILE_HEADER {

WORD Machine; //该文件运行所需要的CPU,对于Intel平台是14Ch

WORD NumberOfSections; //文件的节数目

DWORD TimeDateStamp; //文件创建日期和时间

DWORD PointerToSymbolTable; //用于调试

DWORD NumberOfSymbols; //符号表中符号个数

WORD SizeOfOptionalHeader; //OptionalHeader 结构大小

WORD Characteristics; //文件信息标记,区分文件是exe还是dll

} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_OPTIONAL_HEADER {

WORD Magic; //标志字(总是010bh)

BYTE MajorLinkerVersion; //连接器版本号

BYTE MinorLinkerVersion; //

DWORD SizeOfCode; //代码段大小

DWORD SizeOfInitializedData; //已初始化数据块大小

DWORD SizeOfUninitializedData; //未初始化数据块大小

DWORD AddressOfEntryPoint; //PE装载器准备运行的PE文件的第一个指令的RV A,若要改变整个执行的流程,可以将该值指定到新的RV A,这样新RV A处的指令首先被执行。(许多文章都有介绍RV A,请去了解)

DWORD BaseOfCode; //代码段起始RV A

DWORD BaseOfData; //数据段起始RVA

DWORD ImageBase; //PE文件的装载地址

DWORD SectionAlignment; //块对齐

DWORD FileAlignment; //文件块对齐

WORD MajorOperatingSystemVersion;//所需操作系统版本号

WORD MinorOperatingSystemVersion;//

WORD MajorImageVersion; //用户自定义版本号

WORD MinorImageVersion; //

WORD MajorSubsystemVersion; //win32子系统版本。若PE文件是专门为Win32设计的WORD MinorSubsystemVersion; //该子系统版本必定是4.0否则对话框不会有3维立体感DWORD Win32VersionValue; //保留

DWORD SizeOfImage; //内存中整个PE映像体的尺寸

DWORD SizeOfHeaders; //所有头+节表的大小

DWORD CheckSum; //校验和

WORD Subsystem; //NT用来识别PE文件属于哪个子系统

WORD DllCharacteristics; //

DWORD SizeOfStackReserve; //

DWORD SizeOfStackCommit; //

DWORD SizeOfHeapReserve; //

DWORD SizeOfHeapCommit; //

DWORD LoaderFlags; //

DWORD NumberOfRvaAndSizes; //

IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RV A,比如引入地址表等

} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

typedef struct _IMAGE_DATA_DIRECTORY {

DWORD VirtualAddress; //表的RV A地址

DWORD Size; //大小

} IMAGE_DATA_DIRECTORY, *PIMAGE_DA TA_DIRECTORY;

PE文件头后是节表,在winnt.h下如下定义

typedef struct _IMAGE_SECTION_HEADER {

BYTE Name[IMAGE_SIZEOF_SHORT_NAME];//节表名称,如“.text”

union {

DWORD PhysicalAddress; //物理地址

DWORD VirtualSize; //真实长度

} Misc;

DWORD VirtualAddress; //RVA

DWORD SizeOfRawData; //物理长度

DWORD PointerToRawData; //节基于文件的偏移量

DWORD PointerToRelocations; //重定位的偏移

DWORD PointerToLinenumbers; //行号表的偏移

WORD NumberOfRelocations; //重定位项数目

WORD NumberOfLinenumbers; //行号表的数目

DWORD Characteristics; //节属性

} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

以上结构就是在winnt.h中关于PE文件头的定义,如何我们用C/C++来进行PE可执行文件操作,就要用到上面的所有结构,它详细的描述了PE文件头的结构。

3、修改PE可执行文件

现在让我们把一段代码写入任何一个PE格式的可执行文件,代码如下:

-- test.asm --

.386p

.model flat, stdcall

option casemap:none

include \masm32\include\windows.inc

include \masm32\include\user32.inc

includelib \masm32\lib\user32.lib

.code

start:

INVOKE MessageBoxA,0,0,0,MB_ICONINFORMATION or MB_OK

ret

end start

以上代码只显示一个MessageBox框,编译后得到二进制代码如下:

unsigned char writeline[18]={

0x6a,0x40,0x6a,0x0,0x6a,0x0,0x6a,0x0,0xe8,0x01,0x0,0x0,0x0,0xe9,0x0,0x0,0x0,0x0

};

好,现在让我们看看该把这些代码写到那。现在用Tdump.exe显示一个PE格式得可执行文件信息,可以发现如下描述:

Object table:

# Name VirtSize RV A PhysSize Phys off Flags

-- -------- -------- -------- -------- -------- --------

01 .text 0000CCC0 00001000 0000CE00 00000600 60000020 [CER]

02 .data 00004628 0000E000 00002C00 0000D400 C0000040 [IRW]

03 .rsrc 000003C8 00013000 00000400 00010000 40000040 [IR]

Key to section flags:

C - contains code

E - executable

I - contains initialized data

R - readable

W - writeable

上面描述此文件中存在3个段及每个段得信息,实际上我们的代码可以写入任何一个段,这里我选择“.text”段。

用如下代码得到一个PE格式可执行文件的头信息:

//writePE.cpp

#include

#include

#include

#include

#include

#include

unsigned char writeline[18]={

0x6a,0x40,0x6a,0x0,0x6a,0x0,0x6a,0x0,0xe8,0x01,0x0,0x0,0x0,0xe9,0x0,0x0,0x0,0x0

};

DWORD space;

DWORD entryaddress;

DWORD entrywrite;

DWORD progRA V;

DWORD oldentryaddress;

DWORD newentryaddress;

DWORD codeoffset;

DWORD peaddress;

DWORD flagaddress;

DWORD flags;

DWORD virtsize;

DWORD physaddress;

DWORD physsize;

DWORD MessageBoxAadaddress;

int main(int argc,char * * argv)

{

HANDLE hFile, hMapping;

void *basepointer;

FILETIME * Createtime;

FILETIME * Accesstime;

FILETIME * Writetime;

Createtime = new FILETIME;

Accesstime = new FILETIME;

Writetime = new FILETIME;

if ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INV ALID_HANDLE_V ALUE)//打开要修改的文件

{

puts("(could not open)");

return EXIT_FAILURE;

}

if(!GetFileTime(hFile,Createtime,Accesstime,Writetime))

{

printf("\nerror getfiletime: %d\n",GetLastError());

}

//得到要修改文件的创建、修改等时间

if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONL Y | SEC_COMMIT, 0, 0, 0))) {

puts("(mapping failed)");

CloseHandle(hFile);

return EXIT_FAILURE;

}

if (!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))

{

puts("(view failed)");

CloseHandle(hMapping);

CloseHandle(hFile);

return EXIT_FAILURE;

}

//把文件头映象存入baseointer

CloseHandle(hMapping);

CloseHandle(hFile);

map_exe(basepointer);//得到相关地址

UnmapViewOfFile(basepointer);

printaddress();

printf("\n\n");

if(space<50)

{

printf("\n空隙太小,数据不能写入.\n");

}

else

{

writefile();//写文件

}

if ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INV ALID_HANDLE_V ALUE)

{

puts("(could not open)");

return EXIT_FAILURE;

}

if(!SetFileTime(hFile,Createtime,Accesstime,Writetime))

{

printf("error settime : %d\n",GetLastError());

}

//恢复修改后文件的建立时间等

delete Createtime;

delete Accesstime;

delete Writetime;

CloseHandle(hFile);

return 0;

}

void map_exe(const void *base)

{

IMAGE_DOS_HEADER * dos_head;

dos_head =(IMAGE_DOS_HEADER *)base;

#include

typedef struct PE_HEADER_MAP

{

DWORD signature;

IMAGE_FILE_HEADER _head;

IMAGE_OPTIONAL_HEADER opt_head;

IMAGE_SECTION_HEADER section_header[];

} peHeader;

#include

if (dos_head->e_magic != IMAGE_DOS_SIGNA TURE)

{

puts("unknown type of file");

return;

}

peHeader * header;

header = (peHeader *)((char *)dos_head + dos_head->e_lfanew);//得到PE文件头if (IsBadReadPtr(header, sizeof(*header))

{

puts("(no PE header, probably DOS executable)");

return;

}

DWORD mods;

char tmpstr[4]={0};

DWORD tmpaddress;

DWORD tmpaddress1;

if(strstr((const char *)header->section_header[0].Name,".text")!=NULL)

{

virtsize=header->section_header[0].Misc.VirtualSize;

//此段的真实长度

physaddress=header->section_header[0].PointerToRawData;

//此段的物理偏移

physsize=header->section_header[0].SizeOfRawData;

//此段的物理长度

peaddress=dos_head->e_lfanew;

//得到PE文件头的开始偏移

peHeader peH;

tmpaddress=(unsigned long )&peH;

//得到结构的偏移

tmpaddress1=(unsigned long )&(peH.section_header[0].Characteristics);

//得到变量的偏移

flagaddress=tmpaddress1-tmpaddress+2;

//得到属性的相对偏移

flags=0x8000;

//一般情况下,“.text”段是不可读写的,如果我们要把数据写入这个段需要改变其属性,实际上这个程序并没有把数据写入“.text”段,所以并不需要更改,但如果你实现复杂的功能,肯定需要数据,肯定需要更改这个值,

space=physsize-virtsize;

//得到代码段的可用空间,用以判断可不可以写入我们的代码

//用此段的物理长度减去此段的真实长度就可以得到

progRA V=header->opt_head.ImageBase;

//得到程序的装载地址,一般为400000

codeoffset=header->opt_head.BaseOfCode-physaddress;

//得到代码偏移,用代码段起始RV A减去此段的物理偏移

//应为程序的入口计算公式是一个相对的偏移地址,计算公式为:

//代码的写入地址+codeoffset

entrywrite=header->section_header[0].PointerToRawData+header->section_header[0].Misc.Virtua lSize;

//代码写入的物理偏移

mods=entrywrite%16;

//对齐边界

if(mods!=0)

{

entrywrite+=(16-mods);

}

oldentryaddress=header->opt_head.AddressOfEntryPoint;

//保存旧的程序入口地址

newentryaddress=entrywrite+codeoffset;

//计算新的程序入口地址

return;

}

void printaddress()

{

HINSTANCE gLibMsg=NULL;

DWORD funaddress;

gLibMsg=LoadLibrary("user32.dll");

funaddress=(DWORD)GetProcAddress(gLibMsg,"MessageBoxA"); MessageBoxAadaddress=funaddress;

gLibAMsg=LoadLibrary("kernel32.dll");

//得到MessageBox在内存中的地址,以便我们使用

}

void writefile()

{

int ret;

long retf;

DWORD address;

int tmp;

unsigned char waddress[4]={0};

ret=_open(filename,_O_RDWR | _O_CREAT | _O_BINARY,_S_IREAD | _S_IWRITE); if(!ret)

{

printf("error open\n");

return;

}

retf=_lseek(ret,(long)peaddress+40,SEEK_SET);

//程序的入口地址在PE文件头开始的40处

if(retf==-1)

{

printf("error seek\n");

return;

}

address=newentryaddress;

tmp=address>>24;

waddress[3]=tmp;

tmp=address<<8;

tmp=tmp>>24;

waddress[2]=tmp;

tmp=address<<16;

tmp=tmp>>24;

waddress[1]=tmp;

tmp=tmp>>24;

waddress[0]=tmp;

retf=_write(ret,waddress,4);

//把新的入口地址写入文件

if(retf==-1)

{

printf("error write: %d\n",GetLastError());

return;

}

retf=_lseek(ret,(long)entrywrite,SEEK_SET);

if(retf==-1)

{

printf("error seek\n");

return;

}

retf=_write(ret,writeline,18);

if(retf==-1)

{

printf("error write: %d\n",GetLastError());

return;

}

//把writeline写入我们计算出的空间

retf=_lseek(ret,(long)entrywrite+9,SEEK_SET);

//更改MessageBox函数地址,它的二进制代码在writeline[10]处

if(retf==-1)

{

printf("error seek\n");

return;

}

address=MessageBoxAadaddress-(progRA V+newentryaddress+9+4);

//重新计算MessageBox函数的地址,MessageBox函数的原地址减去程序的装载地址加上新的入口地址加9(它的二进制代码相对偏移)加上4(地址长度)

tmp=address>>24;

waddress[3]=tmp;

tmp=address<<8;

tmp=tmp>>24;

waddress[2]=tmp;

tmp=address<<16;

tmp=tmp>>24;

waddress[1]=tmp;

tmp=tmp>>24;

waddress[0]=tmp;

retf=_write(ret,waddress,4);

//写入重新计算的MessageBox地址

if(retf==-1)

{

printf("error write: %d\n",GetLastError());

return;

}

retf=_lseek(ret,(long)entrywrite+14,SEEK_SET);

//更改返回地址,用jpm返回原程序入口地址,其它的二进制代码在writeline[15]处

if(retf==-1)

{

printf("error seek\n");

return;

}

address=0-(newentryaddress-oldentryaddress+4+15);

//返回地址计算的方法是新的入口地址减去老的入口地址加4(地址长度)加15(二进制代码相对偏移)后取反

tmp=address>>24;

waddress[3]=tmp;

tmp=address<<8;

tmp=tmp>>24;

waddress[2]=tmp;

tmp=address<<16;

tmp=tmp>>24;

waddress[1]=tmp;

tmp=address<<24;

tmp=tmp>>24;

waddress[0]=tmp;

retf=_write(ret,waddress,4);

//写入返回地址

if(retf==-1)

{

printf("error write: %d\n",GetLastError());

return;

}

_close(ret);

printf("\nall done...\n");

return;

}

//end

由于在PE格式的文件中,所有的地址都使用RV A地址,所以一些函数调用和返回地址都要经过计算才可以得到,以上是我在实践中的心得,如果你有更好的办法,真心的希望你能告诉我。

pe文件格式

PE文件格式详解(一)――基础知识 什么是PE文件格式: 我们知道所有文件都是一些连续(当然实际存储在磁盘上的时候不一定是连续的)的数据组织起来的,不同类型的文件肯定组织形式也各不相同;PE文件格式便是一种文件组织形式,它是32位Wind ow系统中的可执行文件EXE以及动态连接库文件DLL的组织形式。为什么我们双击一个EXE文件之后它就会被Window运行,而我们双击一个DOC文件就会被Word打开并显示其中的内容;这说明文件中肯定除了存在那些文件的主体内容(比如EXE文件中的代码,数据等,DOC文件中的文件内容等)之外还存在其他一些重要的信息。这些信息是给文件的使用者看的,比如说EXE文件的使用者就是Window,而DOC文件的使用者就是Word。Window可以根据这些信息知道把文件加载到地址空间的那个位置,知道从哪个地址开始执行;加载到内存后如何修正一些指令中的地址等等。那么PE文件中的这些重要信息都是由谁加入的呢?是由编译器和连接器完成的,针对不同的编译器和连接器通常会提供不同的选项让我们在编译和 联结生成PE文件的时候对其中的那些Window需要的信息进行设定;当然也可以按照默认的方式编译连接生成Window中默认的信息。例如:WindowNT默认的程序加载基址是0x40000;你可以在用VC连接生成EXE文件的时候使用选项更改这个地址值。在不同的操作系统中可执行文件的格式是不同的,比如在Linux上就有一种流行的ELF格式;当然它是由在Linux上的编译器和连接器生成的,

所以编译器、连接器是针对不同的CPU架构和不同的操作系统而涉及出来的。在嵌入式领域中我们经常提到交叉编译器一词,它的作用就是在一种平台下编译出能在另一个平台下运行的程序;例如,我们可以使用交叉编译器在跑Linux的X86机器上编译出能在Arm上运行的程序。 程序是如何运行起来的: 一个程序从编写出来到运行一共需要那些工具,他们都对程序作了些什么呢?里面都涉及哪些知识需要学习呢?先说工具:编辑器-》编译器-》连接器-》加载器;首先我们使用编辑器编辑源文件;然后使用编译器编译程目标文件OBJ,这里面涉及到编译原理的知识;连接器把OBJ文件和其他一些库文件和资源文件连接起来生成EXE文件,这里面涉及到不同的连接器的知识,连接器根据OS的需要生成EXE文件保存着磁盘上;当我们运行EXE文件的时候有W indow的加载器负责把EXE文件加载到线性地址空间,加载的时候便是根据上一节中说到的PE文件格式中的哪些重要信息。然后生成一个进程,如果进程中涉及到多个线程还要生成一个主线程;此后进程便开始运行;这里面涉及的东西很多,包括:PE文件格式的内容;内存管理(CPU内存管理的硬件环境以及在此基础上的OS内存管理方式);模块,进程,线程的知识;只有把这些都弄清楚之后才能比较清楚的了解这整个过程。下面就让我们先来学习PE文件格式吧。

linux下编译C语言

GCC 支持了许多不同的语言,包括C、C++、Ada、Fortran、Objective C,Perl、Python 和Ruby,甚至还有Java。 Linux 内核和许多其他自由软件以及开放源码应用程序都是用 C 语言编写并使用GCC 编译的。 编译C++程序: -c 只编译不连接 g++ file1 -c -o file1.o g++ file2 -c -o file2.o g++ file1.o file.o -o exec g++ -c a.cpp 编译 g++ -o a a.o 生成可执行文件 也可以g++ -o a a.cpp直接生成可执行文件。 1. 编译单个源文件 为了进行测试,你可以创建“Hello World”程序: #include #include int main(int argc, char **argv) { printf(“Hello world!n”); exit(0); } 使用如下命令编译并测试这个代码: # gcc -o hello hello.c

# ./hello Hello wordl! 在默认情况下产生的可执行程序名为a.out,但你通常可以通过gcc 的“-o”选项来指定自己的可执行程序名称。 2. 编译多个源文件 源文件message.c包含一个简单的消息打印函数: #include void goodbye_world(void) { printf(“Goodbye, world!n”); } 使用gcc的“-c”标记来编译支持库代码: # gcc -c message.c 这一过程的输出结果是一个名为message.o的文件,它包含适合连接到一个较大程序的已编译目标代码。 创建一个简单的示例程序,它包含一个调用goodbye_world的main函数 #include void goodbye_world(void): int main(int argc, char **argv) { goodbye_world(); exit(0); }

PE格式基础及程序的装入

DOS MZ header部分是DOS时代遗留的产物,是PE文件的一个遗传基因,一个Win32程序如果在DOS下也是可以执行,只是提示:“This program cannot be run in DOS mode.”然后就结束执行,提示执行者,这个程序要在Win32系统下执行。 DOS stub 部分是DOS插桩代码,是DOS下的16位程序代码,只是为了显示上面的提示数据。这段代码是编译器在程序编译过程中自动添加的。 PE header 是真正的Win32程序的格式头部,其中包括了PE格式的各种信息,指导系统如何装载和执行此程序代码。 Section table部分是PE代码和数据的结构数据,指示装载系统代码段在哪里,数据段在哪里等。对于不同的PE文件,设计者可能要求该文件包括不同的数据的Section。所以有一个Section Table 作为索引。Section多少可以根据实际情况而不同。但至少要有一个Section。如果一个程序连代码都没有,那么他也不能称为可执行代码。在Section Table后,Section数目的多少是不定的。 二、程序的装入 当我们在explorer.exe(资源管理器)中双击某文件,执行一个可执行程序,系统会根据文件扩展名启动一个程序装载器,称之为Loader。Loader会首先检查DOS MZ Header,如果存在,就继续寻找PE header,如果这两项都不存在,就认为是DOS 16位代码,如果只存在DOS MZ Header,而其中又指示了而其中又指示了PE Header 的位置,那么Loader 就判定此文件不一个有效的PE文件,拒绝执行。 如果DOS Header 和PE Header都正常有效,那么Loader就会根据PE Header 及Section Table的指示,将相应的代码和数据映射到内存中,然后根据不同的Section进行数据的初始化,最后开始执行程序段代码。 三、PE格式高级分析 下面我们以一个真实的程序为例详细分析PE格式,分析PE格式最好有PE分析器,常用的软件是Lord PE,也有其它的分析工具和软件如PE Editor 、Stud PE等。 先分析一下磁盘文件的内容,这里我们使用UltraEdit32(UE)工具,这是一个实用的文件编辑器,可以编辑文本和二进制文件。

Linux下Makefile简单教程

目录 一:Makefile基本规则 1.1示例 1.2 隐式规则 1.3 伪目标 1.4 搜索源文件 二:变量 2.1使用变量定义变量值 2.2追加变量 三:条件判断 四:函数

Linux下Makefile总结 ——一步 MakeFile可以看做是一种简单的编程语言,其诞生的本质目的是实现自动化编译。 以Linux下gcc-c编译器为例,编译一个c语言程序需要经过以下几个步骤: 1.将c语言源程序预处理,生成.i文件; 2.预处理后的.i语言编译成汇编语言,生成.s文件; 3.汇编语言经过汇编,生成目标文件.o文件; 4.将各个模块的.o文件链接起来,生成一个可执行程序文件。 我们知道,在Visual C++6.0中,可以新建一个工程,在一个工程当中能够包含若干个c语言文件,则编译的时候直接编译整个工程便可。Linux下无法为多个c语言文件新建工程,但可以通过MakeFile实现它们的整合编译。 如上gcc-c编译步骤,如果使用Makefile则过程为: .C文件——>.o文件——>可执行文件 当然,Makefile中也加入了自己的设置变量方法与集成了一些函数,能够更有效地方便用户使用。 /**************************分隔符********************************/

一:Makefile基本规则 1.1示例 target ... : prerequisites ... command ... ... target也就是一个目标文件,可以是Object File,也可以是执行文件。prerequisites就是,要生成那个target所需要的文件或是目标。command也就是make需要执行的命令。(任意的Shell命令) 为了方便理解,我们来看一个示例: /*Makefile示例*/ edit : main.o kbd.o command.o display.o / insert.o search.o files.o utils.o gcc -o edit main.o kbd.o command.o display.o / insert.o search.o files.o utils.o main.o : main.c defs.h #生成main.o gcc -c main.c

PE文件头解析大全

PE可选头部 PE可执行文件中接下来的224个字节组成了PE可选头部。虽然它的名字是“可选头部”,但是请确信:这个头部并非“可选”,而是“必需”的。OPTHDROFFSET宏可以获得指向可选头部的指针: PEFILE.H #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE + \ sizeof(IMAGE_FILE_HEADER))) 可选头部包含了很多关于可执行映像的重要信息,例如初始的堆栈大小、程序入口点的位置、首选基地址、操作系统版本、段对齐的信息等等。IMAGE_OPTIONAL_HEADER结构如下: WINNT.H typedef struct _IMAGE_OPTIONAL_HEADER { // // 标准域 // USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONG BaseOfData; // // NT附加域 // ULONG ImageBase; ULONG SectionAlignment;

ULONG FileAlignment; USHORT MajorOperatingSystemVersion; USHORT MinorOperatingSystemVersion; USHORT MajorImageVersion; USHORT MinorImageVersion; USHORT MajorSubsystemVersion; USHORT MinorSubsystemVersion; ULONG Reserved1; ULONG SizeOfImage; ULONG SizeOfHeaders; ULONG CheckSum; USHORT Subsystem; USHORT DllCharacteristics; ULONG SizeOfStackReserve; ULONG SizeOfStackCommit; ULONG SizeOfHeapReserve; ULONG SizeOfHeapCommit; ULONG LoaderFlags; ULONG NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; 如你所见,这个结构中所列出的域实在是冗长得过分。为了不让你对所有这些域感到厌烦,我会仅仅讨论有用的——就是说,对于探究PE文件格式而言有用的。 标准域 首先,请注意这个结构被划分为“标准域”和“NT附加域”。所谓标准域,就是和UNIX可执行文件的COFF 格式所公共的部分。虽然标准域保留了COFF中定义的名字,但是Windows NT仍然将它们用作了不同的目的——尽管换个名字更好一些。 ·Magic。我不知道这个域是干什么的,对于示例程序EXEVIEW.EXE示例程序而言,这个值是0x010B

怎样执行在Linux上运行应用程序

如何执行在Linux上运行的应用程序 关键字:Linux 先决条件 要充分理解本文,必须具备Windows 环境下桌面应用程序的工作经验,我认为读者对如何使用Linux 桌面有一个基本的了解。使用一个运行的Linux 计算来机探讨本文的概念和示例是很有帮助的。 概述 有时候第一次在Linux 上运行一个应用程序需要一点额外工作。有些应用程序,比如服务器服务,可能无法安装为服务,因此您需要从命令行启动这些应用程序。对于启动这些应用程序的用户帐户而言,需要在应用程序文件中设置执行许可标志(x)。 运行用户空间应用程序 Linux 在内核空间或用户空间运行进程。用户空间是操作系统的区域,应用程序通常在此运行。简单地说,每个用户帐户有其自己的用户空间,应用程序在这个领域内运行。 默认情况下,只有root 用户有权访问内核空间。root 用户是Linux 中的超级用户,相当于Windows 中的管理员帐户。在root 用户帐户下运行应用程序可能会引起安全风险,是不可取的。 很多服务器服务需要root 权限启动服务。然而,服务启动后,root 帐户通常会将其移至服务帐户。严格地说,Linux 中的服务帐户才是标准的用户帐户。主要区别是服务帐户仅用于运行一个服务,而不是为任何实际登录的用户准备的。 设置权限 您可以使用chmod 命令在一个文件中设置执行权限。在Linux 中,umask 设置通常用来防止下载的文件被执行,也有充分的理由相信,因为它有助于维护Linux 计算机的安全性。 大多数Linux 发行版具有一个值为022 的umask 设置,这意味着,默认情况下一个新文件权限设置为644.权限的数字表示形式采用读(4)、写(2)、执行(1) 的格式。因此,默认权限为644 的应用程序下载意味着文件所有者有读写权限,而组用户和其他用户只有读权限。 例如,为每个人赋予一个文件的执行权限,使用chmod a+x 命令。a 表示所有人,加号(+) 表示添加,而x 表示执行。同样地,如果应用程序是一个服务器服务,您应该确保只有授权帐户才有权执行此服务。 如果一个应用程序能够在标准用户帐户权限下运行,但只有特定组中的用户才需要使用它,您可以将该组所有者权限设置为可执行,然后将这些用户添加到该组中。 更具体地说,您可以在一个可执行文件中设置访问控制列表(ACL) 权限,赋予特定用户或组权限来运行该应用程序。使用setfacl 实用工具设置ACL 权限。 对于这些需要以root 用户启动进程的应用程序,比如服务器服务,您有几个选择。总结了允许用户执行需要root 权限的服务器服务的各种选项。 选项描述 作为root 用户不推荐用于服务器服务。当用户已经知道root 密码而且应用程序泄露不是首要关注问题时,可用于应用程序。 SetUID 由于安全问题,不推荐使用。SetUID 允许标准用户以另一个用户方式,比如root 用户,执行一个文件。 sudo 很常用,并且被认为是一个很好的实践。sudo 授予一个用户或组成员权限以执行可能额外需要root 权限的文件。该用户不需要知道root 密码。 带有文件权限的标准用户帐户在一个文件上为用户所有者、组所有者或其他人(所有人)

PE文件结构

检验PE文件的有效性 <1>首先检验文件头部第一个字的值是否等于IMAGE_DOS_SIGNATURE,是则表示DOS MZ header有效 <2>一旦证明文件的Dos header 有效后,就可用e_lfanew来定位PE header <3>比较PE header 的第一个字的值是否等于IMAGE_NT_HEADER,如果前后两个值都匹配. PS.WinHex使用方法 1.Alt+G跳到指定位置 2.Ctrl+Shift+N放入新文件 3.大文件扩容,新建一个扩容大小+1的文件,把这个文件的数据复制后写入整个文件的尾地址. 4.文本搜索ctrl+F 5.十六进制搜索ctrl+alt+x 6.文本显示F7 7.打开内存alt+F9 8.进制转换器F8 9.分析选块F2 10.计算HASH ctrl+F2 11.收集文本信息ctrl+F10 12.编辑模式F6 一.IMAGE_DOS_HEADER <1>位置00H,WORD(2个字节)的e_magic为4D5A,即MZ <2>位置3CH,60,LONG(4个节节)的e_lfanew为64+112=176即B0H, 二.IMAGE_NT_HEADERS <1>位置B0H,DWORD(4个字节),PE开始标记,写入50450000,即PE <2>位置B4H,WORD,PE所要求的CPU,对于Intel平台,为4C01 <2>位置B6,WORD,PE中段总数,计划有3个段,.text代码段,.rdata只读数据段,.data全局变量数据段,所以值为0300, <3>位置C4,WORD,表示后面的PE文件可选头的占空间大小,即224字节(E0),值为E000 <4>位置C6,WORD,表示文件是EXE还是DLL,如果是可执行文件写0200,如果是dll,写0020, <5>位置C8,WORD,表示文件格式,如果是0B01表示.exe,如果是0701表示ROM映像

怎么在linux操作系统上安装可执行的软件

仅以RedHat Linux 为参照,包括但不限于其他版本的Linux都要遵循此方法,以下是说明: 先来看看Linux软件扩展名。软件后缀为.rpm最初是Red Hat Linux提供的一种包封装格式,现在许多Linux发行版本都使用;后缀为.deb是Debain Linux 提供的一种包封装格式;后缀为.tar.gz、tar.Z、tar.bz2或.tgz是使用Unix 系统打包工具tar打包的;后缀为.bin的一般是一些商业软件。通过扩展名可以了解软件格式,进而了解软件安装。 RPM格式软件包的安装 1.简介 几乎所有的Linux发行版本都使用某种形式的软件包管理安装、更新和卸载软件。与直接从源代码安装相比,软件包管理易于安装和卸载;易于更新已安装的软件包;易于保护配置文件;易于跟踪已安装文件。 RPM全称是Red Hat Package Manager(Red Hat包管理器)。RPM本质上就是一个包,包含可以立即在特定机器体系结构上安装和运行的Linux软件。RPM 示意图见图1。 大多数Linux RPM软件包的命名有一定的规律,它遵循名称-版本-修正版-类型-MYsoftware-1.2 -1.i386.rpm 。 2.安装RPM包软件 #rpm -ivh MYsoftware-1.2 -1.i386.rpm RPM命令主要参数: -i 安装软件。 -t 测试安装,不是真的安装。 -p 显示安装进度。 -f 忽略任何错误。 -U 升级安装。 -v 检测套件是否正确安装。 3.卸载软件 #rpm -e 软件名 需要说明的是,上面代码中使用的是软件名,而不是软件包名。例如,要卸载software-1.2.-1.i386.rpm这个包时,应执行: #rpm -e software 4.强行卸载RPM包

如何在linux中自由执行python程序

可执行的Python程序 这部分内容只对Linux/Unix用户适用,不过Windows用户可能也对程序的第一行比较好奇。首先我们需要通过chmod命令,给程序可执行的许可,然后运行程序。 chmod命令用来改变文件的模式,给系统中所有用户这个源文件的执行许可。然后我们可以直接通过指定源文件的位置来执行程序。我们使用./来指示程序位于当前目录。 为了更加有趣一些,你可以把你的文件名改成仅仅helloworld,然后运行./helloworld。这样,这个程序仍然可以工作,因为系统知道它必须用源文件第一行指定的那个解释器来运行程序。 只要知道程序的确切位置,你现在就可以运行程序了——但是如果你希望你的程序能够从各个位置运行呢?那样的话,你可以把你的程序保存在PATH环境变量中的目录之一。每当你运行任何程序,系统会查找列在PATH环境变量中的各个目录。然后运行那个程序。你只要简单地把这个源文件复制到PATH所列目录之一就可以使你的程序在任何位置都可用了。

我们能够用echo命令来显示PATH变量,用$给变量名加前缀以向shell 表示我们需要这个变量的值。我们看到/home/swaroop/bin 是PATH变量中的目录之一。swaroop是我的系统中使用的用户名。通常,在你的系统中也会有一个相似的目录。你也可以把你选择的目录添加到PATH变量中去——这可以通过运行PATH=$PATH:/home/swaroop/mydir完成,其中“/home/swaroop/mydir”是我想要添加到PATH变量中的目录。 当你想要在任何时间、任何地方运行你的程序的时候,这个方法十分有用。它就好像创造你自己的指令,如同cd或其他Linux终端或DOS提示符命令那样。

linux下编写c源程序并编译运行

姓名:雨田河南大学rjxy 班级:XXXX 实验二Linux基本操作 实验二Linux基本操作 编写c源程序并用编译运行 【需求】 ◆在当前目录下创建新文件t.c,用vi编辑器一段简单代码,代码要求在屏幕上输出 文字“Hello Linux!”; ◆用gcc编译t.c文件,并运行,查看输出结果,若结果错误,请根据提示修改;【系统及软件环境】 操作系统:Virtualbox,Fedora 13 【实验配置文件及命令】 1.配置文件: 2.命令:touch、rpm、gcc、./等

进入Linux操作系统,应用程序-> 系统工具-> 终端,输入命令:su 输入密码切换到root超级用户。 1.在当前目录建立一个新的目录test:$ mkdir test 在test目录下建立文件t.c :$touch t.c 3编辑程序源代码:vi t.c 首先按下键盘的“i”键,字符界面下方出现“insert”提示字符,此时输入以下代码: #include "stdio.h" int main() { printf("Hello Linux!\n"); return 0; } 4 保存退出:先按下“Esc”键,然后按下“shift”和“:”键,界面上出现冒号,然后输入“xq!”或者“x”对代码保存退出。 5 由于系统默认没有安装C语言编译程序,下面进行安装gcc 程序; 此处不再赘述,以下引用实验指导书: 1.gcc的安装 (1)查看gcc是否安装 rpm –q gcc (2)指定安装源 在“系统-分配光驱”里选择“Fedora-13-i386-DVD.iso” (3)查看安装源挂载位置 df命令,可查看到虚拟光驱挂载点 返回结果为:/media/Fedora 13 i386 DVD (4)使用安装源 安装的文件为RPM安装包,所在位置为安装光盘中的“Packages”目录下,可用“cd”命令进入此目录 cd /media/ Fedora 13 i386 DVD/Packages ★由于“Fedora 13 i386 DVD”名字中有空格,若直接输入,则会提示找不到此目录,可用“tab”键自动补全 【方法】cd /media/F)/P() 则可返回如下结果: cd /media/Fedora\ 13\ i386 \DVD\ /Packages (5)查看当前目录下是否有gcc安装包

pe文件结构 入门 教程

三年前,我曾经写了一个手工打造可执行程序的文章,可是因为时间关系,我的那篇文章还是有很多模糊的地方,我一直惦记着什么时候再写一篇完美的,没想到一等就等了三年。因为各种原因直到三年后的今天我终于完成了它。现在把它分享给大家,希望大家批评指正。 我们这里将不依赖任何编译器,仅仅使用一个十六进制编辑器逐个字节的手工编写一个可执行程序。以这种方式讲解PE结构,通过这个过程读者可以学习PE结构中的PE头、节表以及导入表相关方面的知识。为了简单而又令所有学习程序开发的人感到亲切,我们将完成一个Hello World! 程序。功能仅仅是运行后弹出一个消息框,消息框的内容是Hello World!。 首先了解一下Win32可执行程序的大体结构,就是通常所说的PE结构。 如图1所示PE结构示意图: 图1 标准PE结构图 由图中可以看出PE结构分为几个部分: MS-DOS MZ 头部:所有PE文件必须以一个简单的DOS MZ 头开始。有了它,一旦程序在DOS下执行,DOS就能识别出这是有效的执行体,然后运行紧随MZ header 之后的DOS程序。以此达到对Dos系统的兼容。(通常情况DOS MZ header总共占用64byte)。 MS-DOS 实模式残余程序:实际上是个有效的EXE,在不支持PE文件格式的操作系统中,它将简单显

示一个错误提示,大多数情况下它是由汇编编译器自动生成。通常,它简单调用中断21h,服务9来显示字符串"This program cannot run in DOS mode"。(在我们写的程序中,他不是必须的,可以不予以实现,但是要保留其大小,大小为112byte,为了简洁,可以使用00来填充。) PE文件标志:是PE文件结构的起始标志。(长度4byte, Windows程序此值必须为0x50450000) PE文件头:是PE相关结构 IMAGE_NT_HEADERS 的简称,其中包含了许多PE装载器用到的重要域。执行体在支持PE文件结构的操作系统中执行时,PE装载器将从DOS MZ header中找到PE header的起始偏移量,跳过了MS-DOS 实模式残余程序,直接定位到真正的文件头PE header,长度20byte。 PE文件可选头:虽然它的名字是“可选头部”,但是请确信:这个头部并非“可选”,而是“必需”的。(长度 224byte )。 各段头部:又称节头部,一个Windows NT的应用程序典型地拥有9个预定义段(节),它们是“.text”、“.bss”、“.rdata”、“.data”、“.rsrc”、“.edata”、“.idata”、“.pdata”和“.debug”。一些应用程序不需要所有的这些段,同样还有些应用程序为了自己特殊的需要而定义了更多的段。(每个段头部占40byte,我们这里也不需要所有的段,仅需3个段。) 通常我们是将PE整个结构分成四个部分,把MS-DOS MZ 头部和MS-DOS 实模式残余程序作为第一部分,可以称他为DOS部分,而PE文件标志、PE文件头、PE文件可选头三个部分作为第二部分,称之为PE头部分,因为这部分才是Windows下真正需要的部分,所以从PE文件标志开始才是真正的PE部分。各段头部是第三部分,称之为节表。它详细描述了PE文件中各个节的详细信息。最后就是各个节的实体部分了,称为节数据。 以上仅仅是对PE结构各部分的大体讲解。接下来再手写这个Hello World!程序过程中,我将详细介绍每个部分的含义。 首先准备一下工具,一个十六进制编辑器足以。我们这里使用VC++ 6.0所携带的十六进制编辑器,您也可以使用如WinHex等十六进制编辑工具。 打开VC,选择文件,新建菜单项,然后选择一个二进制文件,单击确定。一切就绪了,下面就开始手写可执行程序,如图2所示:

linux命令--RUN

linux命令 一、linux各种版本 linux命令是对Linux系统进行管理的命令。对于Linux系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与之前的DOS命令类似。linux命令在系统中有两种类型:内置Shell命令和Linux命令。 二、Linux基本操作命令 首先介绍一个名词“控制台(console)”,它就是我们通常见到的使用字符操作界面的人机接口,例如dos。我们说控制台命令,就是指通过字符界面输入的可以操作系统的命令,例如dos命令就是控制台命令。我们现在要了解的是基于Linux操作系统的基本控制台命令。有一点一定要注意,和dos命令不同的是,Linux的命令(也包括文件名等等)对大小写是敏感的,也就是说,如果你输入的命令大小写不对的话,系统是不会做出你期望的响应的。 2.1 模式切换 1、由字符到图型#startx或#init 5 2、由图形到字符#logout或init 3 3、注销#logout或exit或ctrl+d 4、关机#poweroff或init 0或shutdown now或 halt -p 5、重启#reboot或init 6或shutdown -r now 2.2 获得帮助 #help提供内部命令的帮助#man或info提供外部命令的帮助。 如果你的英文足够好,那完全可以不靠任何人就精通linux,只要你会用man。Man实际上就是察看指令用法的help,学习任何一种UNIX类的操作系统最重要的就是学会使用man这个辅助命令。man是manual(手册)的缩写字,它的说明非常的详细,但是因为它都是英文,看起来非常的头痛。建议大家需要的时候再去看man,平常吗,记得一些基本用法就可以了。 2.3 ls ls [list]

PE结构4——区段与代码类型

甲壳虫免杀VIP教程 https://www.doczj.com/doc/b316925700.html, 专业的免杀技术培训基地 我们的口号:绝对不一样的免杀教程!绝对不一样的实战体验!清晰的思路!细致全面的讲解!让你感到免杀原来可以这么简单! 动画教程只是起到技术交流作用.请大家不用利用此方法对国内的网络做破坏. 国人应该团结起来一致对外才是我们的责任.由此动画造成的任何后果和本站 无关. -------------------------------------------------------------------- 【免杀PE结构班】制作:Just41(carrieyz) 第四节【PE文件常见区段及其代码类型】 一、区段表的结构 PE文件格式中,所有的区段信息位于可选PE头之后。每个区段信息为40个字节长,并且没有任何填充信息。区段信息被定义为以下的结构: 学名:免杀技术说明大小LOADPE Name:区段名称,如".text" [8h] SizeOfRawData:RV A偏移大小[4h] VSize VirtualAddress:区段RV A起始地址[4h] VOffset PointerToRawData:区段物理偏移大小(偏移量)[4h] RSize PhysicalAddress:区段物理起始地址[4h] ROffset VirtualSize:真实长度[4h] PointerToRelocations:重定位的偏移[4h] PointerToLinenumbers:行号表的偏移[4h] NumberOfRelocations:重定位项数目[2h] NumberOfLinenumbers:行号表的数目[2h] Characteristics:区段属性[4h] 标志 计算方式: 区段表的文件偏移地址=PE头的文件偏移地址+14h+可选PE头大小+1 首先从0X3Ch处得到PE头的文件偏移地址,然后由PE头的文件偏移地址+14h得到可选PE头大小,再将上面三个数据相加再+1就得到区段表的文件偏移地址了。 VSize的大小只是效验下是否跨越下一个节了,或者是否超出了SizeOfImage,如果出现越界问题,提示非法32位应用程序,否则的话,它的值没有意义,节的大小不是由它决定的......对非最后一个节,按节间VOffset之差,最后一节用SizeOfImage-VOffset。

(完整word版)Linux操作系统(下)复习题

复习题 一、填空题 1、Linux操作系统是Unix 操作系统的一个克隆版本。 2、Linux的命令运行环境昌Shell,它是一种命令解释器,在用户和操作系统之间提供了一个交互接口。 3、Linux系统中有三个基本的文件类型:普通文件、目录文件和设备文件。 4、Linux系统通过目录将系统中所有的文件分级、分层组织在一起,形成了Linux文件系统的树型层次结构。 5、在Linux系统中建立新目录的命令是mkdir 。 6、Linux编程可分为Shell 编程和高级语言编程。 7、Linux系统提供了许多文本编辑程序,比较常用的有vi 和emacs 等。 8、要使用make,必须编写一个叫Makefile 的文件。 9、autoconf 是一个用于生成可以自动配置软件源代码包以适应多种类Unix系统的shell 脚本的工具。 10、Automake 是一个从文件Makefile.am中自动生成Makefile.in文件的工具。 11、Linux的文件是个简单的字节序列。 12、对于Linux而言,所有对设备和文件的操作都使用文件描述符。 13、调用open 函数可以打开或创建一个文件。 14、设置文件的存取权限,分为属主、组用户和其他用户三类。每类分为读、写和执行权限。 15、第一个进程都有一个目录与之相连,它称为当前工作目录,或简单地称为工作目录。 16、当打开一个流时,标准输入输出函数返回一个FILE结构的指针。 17、在三个流是在执行程序时自动打开的。它们是标准输入、标准输出和标准错误输出。 18、有3种类型的无格式I/O 函数可用来读写流,它们是字符I/O函数、行I/O函数和块I/O函数。 19、每一个流对象内部都保持着两个指示器:一个是错误指示器,当读写文件出错时该指示器被设置;另一个为文件结束指示器,当遇到文件尾时该指示器被设置。 20、流有3种不同的缓冲类型,它们是全缓冲、行缓冲和无缓冲。 21、进程在其生存期内可能处于三种基本状态:运行态、就绪态、等待态。 22、为了让Linux来管理系统中的进程,每个进程用一个task_struct 数据结构来表示。 23、在Linux系统中,进程有两种运行模式:用户模式和系统模式。 24、创建一个新进程的唯一方法是由某个已存在的进程调用fork 或vfork 函数,被创建的新进程称为子进程,已存在的进程称为父进程。 25、系统中的每个进程都有唯一的非负整数作为标识,它被称为进程标识号。 26、进程间通信有如下一些目的:数据传输、共享数据、通知事件、资源共享、进程控制. 27、Linux支持Unix System v中的三种进程间通信机制,它们是:消息队列、信号量、共享内存。

pe文件格式

pe文件格式:PE文件格式(1) 疯狂代码 https://www.doczj.com/doc/b316925700.html,/ ?:http:/https://www.doczj.com/doc/b316925700.html,/Waigua/Article60255.html 介绍说明:希望本文能够对初级入门CRACKER有定帮助翻译存在疏漏或者不准确希望来信指出感谢您指导!感谢看雪为我们提供这个交流平台让我们技术和时俱进!! 前言: PE("portableexecutable")文件格式是针对MSwindowsNT,windows95and win32s可执行 2进制代码(DLLsandprograms)在windowsNT内,驱动也是这个格式也可以用于对象文件和库 这个格式是Microsoft设计并在1993经过TIS(toolerfacestandard)委员会 (Microsoft,Intel,Borland,Watcom,IBM等)标准化了它基于在UNIX和VMS上运行对象文件和可执行文件COFF"commonobjectfileformat"格式 win32SDK包括个头文件包括对PE格式定义我将提及成员名和定义你也可能发现DLL文件"imagehelp.dll"非常有用它是NT部分但文档很少它些在"DeveloperNetwork"被描述 总览: 在PE文件开始我们可以发现MSDOS执行部分("stub");这使得任何个PE文件是有效DOS执行文件在DOS-stub的后是32位魔数0x00004550(IMAGE_NT_SIGNATURE).然后是个COFF格式文件头指明在何种机器上运行多少个节在里面连接时间是否是可执行文件或者DLL等DLL和可执行文件区别:DLL不能够启动只可以被其他可执行文件使用个可执行文件不能够连接到另个可执行文件 接着我们看到个可选文件头optionalheader(虽然叫“可选”它实际上直存在) COFF把可选文件头用于库不用于目标文件这里告诉我们文件如何被调入:起始地址预留堆栈数数据段尺寸 个有趣部分是尾巴上数据目录datadirectories这些目录包含指向节内数据指针例如如果文件有输出目录可以在成员IMAGE_DIRECTORY_ENTRY_EXPORT内发现个指针指向那个目录(目录描述结构->THUNKDATA结构->BYNAME结构)他将指向个节 在头后面是节头实际上节内容就是真正需要运行个所需要东西所有头和目录成员就是帮你找到它每个节有几个标志:对齐包含数据类型(化数据等)是否可以共享等及数据自身多数节含有个或多个通过“可选头”内数据目录项引用目录没有目录类型内容是化数据或者可执行代码(节是物理意义上内容组织目录是逻辑意义上内容

linux操作系统考试题库完整

1.在Linux目录结构中目录中的文件是普通用户可以使用的可使用的可执行文件的目录是(B)19 A./sbin B./bin C./usr D./lib 2.在Linux目录结构中Linux的内核及引导程序所需要的文件位于(B)目录 A/bin B./boot C./root D./proc 3.在Linux目录结构中用来存放系统配置文件(D)目录 A./lib B./dev C./proc D./etc 4.Linux三种特殊权限中仅用于目录文件的权限是(C)22 A.SUID B.SGID C.黏滞位 D.都可以 5.Linux三种权限中允许进入目录的权限(C) 22 A.r-可读 B.w-可写 C.x-可执行 D.都不是 6.下列脚本文件最先自动执行的是(A)24 A./etc/rc.local B./etc/profile C.~/.bashrc D.~/.bash_logout 7.下面通配符可匹配多个任意字符的通配符是(A)29 A.* B. ? C.[abcde ] D.[!a-e] 8.输出重定向符号右边的文件已经存在,不会覆盖文件而是追加的定向符是(B) A.> B.> > C. 2> D.&> 9.表示用户家目录的是(B) A./home (所有用户家目录的父目录,+用户名才是用户家目录) B.~ C. . D. .. 10.可删除非空目录及其子目录的命令是(B) A. touch B.rm -r C.mkdir D.rmdir空目录 11. 是强引用的符号(A) A. 单引号 B.反引号 C.双引号 D.中括号 12.可显示隐藏文件的ls命令形式选项是(A) A. ls -a B. ls -d C.ls -h D .ls -l 13.可通过接受标准输入作为输出内容来创建简单文件的命令是(B)42 A.touch B.cat C.vi D. gedit 14.不带有编辑功能但有翻页、按行滚动、搜索功能的命令是(B)43 A.cat B.more和less C.head 和tail D vi 15.wc命令可统计文件的行数、字数和字节数。在下列格式中只显示文件的字数的是(C)51 A.wc B. wc -c C. wc -w D wc -l 16.可实现文件重命名的命令是(B)52 A.cp B. mv C. ln D rename

【翻译】“PE文件格式”1.9版 完整译文(附注释)

标题:【翻译】“PE文件格式”1.9版完整译文(附注释) 作者:ah007 时间: 2006-02-28,13:32:12 链接: https://www.doczj.com/doc/b316925700.html,/showthread.php?t=21932 $Id: pe.txt,v 1.9 1999/03/20 23:55:09 LUEVELSMEYER Exp $ PE文件格式系列译文之一---- 【翻译】“PE文件格式”1.9版完整译文(附注释) ========================================================= 原著:Bernd. Luevelsmeyer 翻译:ah007 [注意:本译文的所有大小标题序号都是译者添加,以方便大家阅读。圆圈内的数字是注释的编号,其中注释②译自微软的《PECOFF规范》,其它译自网络。----译者] 一、前言(Preface) ------------------ PE(“portable executable”,可移植的可执行文件)文件格式,是微软WindwosNT,Windows95和Win32子集①中的可执行的二进制文件的格式;在WindowsNT中,驱动程序也是这种格式。它还能被应用于各种目标文件②和库文件中。 这种文件格式是由微软设计的,并于1993年被TIS(tool interface standard,工具接口标准)委员会(由Microsoft,Intel,Borland,Watcom,IBM,等等组成)所批准,它明显的基于COFF文件格式的许多知识。COFF (“common object file fromat”,通用目标文件格式)是应用于好几种UNIX系统③和VMS④系统中的目标文件和可执行文件的格式。 Win32 SDK⑤中包含一个名叫的头文件,其中含有很多用于PE格式的#define和typedef定义。我将逐步地提到其中的很多结构成员名字和#define定义。 你也可能发现DLL文件“imagehelp.dll”很有用途,它是WindowNT的一部分,但其书面文件却很缺乏。它的一些功用在“Developer Network”(开发者网络)中有所描述。 二、总览(General Layout) ------------------------- 在一个PE文件的开始处,我们会看到一个MS-DOS可执行体(英语叫“stub”,意为“根,存根”);它使任何PE文件都是一个有效的MS-DOS可执行文件。 在DOS-根之后是一个32位的签名以及魔数0x00004550 (IMAGE_NT_SIGNATURE)(意为“NT签名”,也

相关主题
相关文档 最新文档