1. LLP64 数据模型
数据模型 short int long longlong 指针 操作系统类型
ILP32 2 4 4 8 4 win32
LLP64 2 4 4 8 8 windows 64 位
LP64 2 4 8 8 8 UNIX 64 位
2.WOW64 参考: https://msdn.microsoft.com/en-us/library/aa384249(v=vs.85).aspx
在64bit windows系统中, 64bit程序加载kernel32.dll和ntdll.dll等dll文件都是64bit的,而
32bit程序加载的kernel32.dll和ntdll.dll等dll文件都是32bit的
前者的dll模块在C:\windows\system32\ 目录下
后者的dll模块在C:\windows\sysWOW64\ 目录下
WOW64 机制会将32bit程序的API调用重定向到64bit的dll中.即API调用过程:
程序->kernel32.dll(32bit的)->ntdll.dll(32bit的)->WOW64->ntdll.dll(64bit)->内核(64bit)
此外WOW64机制只运行在ring3层上,内核驱动程序在64bit系统上必须编译成64bit的才能运行,否则会导致蓝屏
WOW64的文件夹,注册表重定向机制: 32bit和64bit程序调用GetSystemDirectory()时都返回 C:\windows\system32\
而实际上32bit程序本应该返回C:\windows\sysWOW64\. WOW64机制将其修改掉名字,而32bit程序如果操作该目录时还是
操作了C:\windows\sysWOW64\ 目录,只是显示的名字是C:\windows\system32\
注册表操作同样被重定向,例如HKLM\SOFTWARE\的键时将被定向到HKLM\SOFTWARE\Wow6432Node
3.通用寄存器
e编程r, 共8字节, 低4字节仍然叫e.. 如 rax, eax, ax, al
call和jmp 指令 操作数. 当call和jmp的操作数是个从地址取数时使用相对偏移.例如:
x z call qword ptr [y]
x是该指令地址,8字节, z是该指令的机器码,6字节, y是个地址,8字节 即z的前2字节是call的机器码,为ff15 然后的值= y-x-6 取后4字节的值
4.函数调用约定
debug模式:
main截取:
DWORD n = test64(1, 2, 3, 4, 5, 6, 7); 00007FF672041AAE mov dword ptr [rsp+30h],7 00007FF672041AB6 mov dword ptr [rsp+28h],6 00007FF672041ABE mov dword ptr [rsp+20h],5 00007FF672041AC6 mov r9d,4 00007FF672041ACC mov r8d,3 00007FF672041AD2 mov edx,2 00007FF672041AD7 mov ecx,1 00007FF672041ADC call test64 (07FF67204134Dh) 00007FF672041AE1 mov dword ptr [n],eax
DWORD WINAPI test64(int a, int b, int c, int d, int e, int f, int g)
{
00007FF6038C34F0 mov dword ptr [rsp+20h],r9d
00007FF6038C34F5 mov dword ptr [rsp+18h],r8d
00007FF6038C34FA mov dword ptr [rsp+10h],edx
00007FF6038C34FE mov dword ptr [rsp+8],ecx
00007FF6038C3502 push rbp
00007FF6038C3503 push rdi
00007FF6038C3504 sub rsp,0C8h ;提高栈顶来存变量
00007FF6038C350B mov rbp,rsp
00007FF6038C350E mov rdi,rsp
00007FF6038C3511 mov ecx,32h
00007FF6038C3516 mov eax,0CCCCCCCCh
00007FF6038C351B rep stos dword ptr [rdi]
00007FF6038C351D mov ecx,dword ptr [rsp+0E8h]
return a + b + c + d + e + f + g;
00007FF6038C3524 mov eax,dword ptr [b]
00007FF6038C352A mov ecx,dword ptr [a]
00007FF6038C3530 add ecx,eax
00007FF6038C3532 mov eax,ecx
00007FF6038C3534 add eax,dword ptr [c]
00007FF6038C353A add eax,dword ptr [d]
00007FF6038C3540 add eax,dword ptr [e]
00007FF6038C3546 add eax,dword ptr [f]
00007FF6038C354C add eax,dword ptr [g]
}
00007FF6038C3552 lea rsp,[rbp+0C8h] ;回收
00007FF6038C3559 pop rdi
00007FF6038C355A pop rbp
00007FF6038C355B ret
1.64bit的call前4个参数通过ecx,edx,r8d,r9d 寄存器传递, 后续的参数通过栈传递. 且直接将参数写到栈中,而不是通过push指令
2.代码中指定了WINAPI(即__stdcall)调用方式仍然不以__stdcall方式传递参数. 通过栈传递的参数也没有移动rsp,只是以rsp作为基址来保存
参数
3.被调用函数中并没有平衡参数的栈帧
4.返回值仍然通过rax传递
release 模式:
int main() { 00007FF79A661000 sub rsp,48h handle_t a = CreateFile(0, 0, 0, 0, 0, 0, 0); 00007FF79A661004 xor eax,eax 00007FF79A661006 xor r9d,r9d 00007FF79A661009 mov qword ptr [rsp+30h],rax 00007FF79A66100E xor r8d,r8d 00007FF79A661011 mov dword ptr [rsp+28h],eax 00007FF79A661015 xor edx,edx 00007FF79A661017 xor ecx,ecx 00007FF79A661019 mov dword ptr [rsp+20h],eax 00007FF79A66101D call qword ptr [__imp_CreateFileW (07FF79A662000h)] return 1; 00007FF79A661023 mov eax,1 } 00007FF79A661028 add rsp,48h } 00007FF79A66102C ret
1.main函数中调用CreateFile 时,传递参数和debug模式是一样的规则
2.main函数中直接通过rsp减去48h来保存这次的变量和参数的占用的空间,根本没有用到rbp和push,pop指令建立栈帧
3.传递参数时rsp从20h开始(从第5个参数开始向后看), 说明rsp为前4个参数预留了空间
CreateFileW:
00007FFE1EB57158 sub rsp,58h 00007FFE1EB5715C mov r10d,dword ptr [rsp+88h] 00007FFE1EB57164 mov dword ptr [rsp+30h],20h 00007FFE1EB5716C mov eax,r10d 00007FFE1EB5716F and eax,7FB7h 00007FFE1EB57174 mov dword ptr [rsp+34h],eax 00007FFE1EB57178 mov eax,r10d 00007FFE1EB5717B and eax,0FFF00000h 00007FFE1EB57180 mov dword ptr [rsp+38h],eax 00007FFE1EB57184 bt r10d,14h 00007FFE1EB57189 jb 00007FFE1EB5A6E5 00007FFE1EB5718F and dword ptr [rsp+3Ch],0 00007FFE1EB57194 mov rax,qword ptr [rsp+90h] 00007FFE1EB5719C and dword ptr [rsp+28h],0 00007FFE1EB571A1 mov qword ptr [rsp+40h],r9 00007FFE1EB571A6 mov r9d,dword ptr [rsp+80h] 00007FFE1EB571AE mov qword ptr [rsp+48h],rax 00007FFE1EB571B3 lea rax,[rsp+30h] 00007FFE1EB571B8 mov qword ptr [rsp+20h],rax 00007FFE1EB571BD call 00007FFE1EB571D0 00007FFE1EB571C2 add rsp,58h 00007FFE1EB571C6 ret
5.PE32+ 与PE32比较
nt头:
typedef struct _IMAGE_NT_HEADERS64 { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER64 OptionalHeader; //不同 } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; //不同 } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
可选头:
typedef 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; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; //下面几个栈堆字段类型不同 DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;typedef struct _IMAGE_OPTIONAL_HEADER64 { WORD Magic;
BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; ULONGLONG ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
IMAGE_THUNK_DATA:
typedef struct _IMAGE_THUNK_DATA32 { union { DWORD ForwarderString; // PBYTE DWORD Function; // PDWORD DWORD Ordinal; DWORD AddressOfData; // PIMAGE_IMPORT_BY_NAME } u1;//类型不同 } IMAGE_THUNK_DATA32; typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
typedef struct _IMAGE_THUNK_DATA64 { union { ULONGLONG ForwarderString; // PBYTE ULONGLONG Function; // PDWORD ULONGLONG Ordinal; ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME } u1; } IMAGE_THUNK_DATA64; typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64;
导入表描述符倒是一样的
typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // 0 for terminating null import descriptor DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) } DUMMYUNIONNAME; DWORD TimeDateStamp; // 0 if not bound, // -1 if bound, and real date\time stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND) DWORD ForwarderChain; // -1 if no forwarders DWORD Name; DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR; typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
线程局部存储:
typedef struct _IMAGE_TLS_DIRECTORY64 { ULONGLONG StartAddressOfRawData; ULONGLONG EndAddressOfRawData; ULONGLONG AddressOfIndex; // PDWORD ULONGLONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; DWORD SizeOfZeroFill; union { DWORD Characteristics; struct { DWORD Reserved0 : 20; DWORD Alignment : 4; DWORD Reserved1 : 8; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; } IMAGE_TLS_DIRECTORY64; typedef IMAGE_TLS_DIRECTORY64 * PIMAGE_TLS_DIRECTORY64; typedef struct _IMAGE_TLS_DIRECTORY32 { DWORD StartAddressOfRawData; DWORD EndAddressOfRawData; DWORD AddressOfIndex; // PDWORD DWORD AddressOfCallBacks; // PIMAGE_TLS_CALLBACK * DWORD SizeOfZeroFill; union { DWORD Characteristics; struct { DWORD Reserved0 : 20; DWORD Alignment : 4; DWORD Reserved1 : 8; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; } IMAGE_TLS_DIRECTORY32; typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32;
6.nt6.0及以上的内核的会话隔离机制
基本介绍
系统重要进程和服务进程都运行在会话0中, 而用户登录后启动的程序都在该用户所在的会话中,包括explorer. 在用户会话向
会话0中的进程进行一些操作时将会有些麻烦.