从Platform Builder来看,Windows CE支持相当多CPU,但现在市场上实际销售的PDA几乎全部采用ARM芯片。ARM是一个RISC构架的32位微处理器,它一次有16个可见的寄存器:r0-r15。其中r0-r7是通用寄存器并可以做任何目的;r8-r12也是通用寄存器,但是在切换到FIQ模式的时候,使用它们的影子(shadow)寄存器;最后这三个是特殊寄存器:
r13 (sp)
-
堆栈指针
r14 (lr)
-
链接寄存器
r15 (pc/psr) -
程序计数器/状态寄存器
IDAPro和调试器里都是用别名表示。和其它RISC指令类似,ARM指令主要有分支(branch)指令、载入和存储指令和其它指令等,除了载入和存储指令,其它指令都是不能直接操作内存的,而且载入和存储指令操作的是4字节类型,那么内存地址必须要求4字节对齐,这也是RISC指令和CISC指令差异比较大的地方,在操作字符串的时候相对就比较麻烦。ARM指令一个很有趣的地方就是可以直接修改访问pc寄存器,这样如果写shellcode的话就不必象SPARC或PowerPC一样需要多条指令来定位自身。
另外Windows CE默认使用的字节序是little-endian。
--[ 2. Windows CE核心结构
Windows CE是一个32位的操作系统,所以其虚拟内存的大小是4GB(2的32次方)。Windows CE把这4GB虚拟内存空间分为低地址2GB和高地址2GB。应用程序使用的地址空间是低地址2GB,高地址2GB专供Windows CE内核使用。在Windows CE 3.0源码的PRIVATE/WINCEOS/COREOS/NK/INC/nkarm.h头文件里有一些有趣的信息:
/* High memory layout
*
* This structure is mapped in at the end of the 4GB virtual
* address space.
*
*
0xFFFD0000 - first level page table (uncached) (2nd half is r/o)
*
0xFFFD4000 - disabled for protection
*
0xFFFE0000 - second level page tables (uncached)
*
0xFFFE4000 - disabled for protection
*
0xFFFF0000 - exception vectors
*
0xFFFF0400 - not used (r/o)
*
0xFFFF1000 - disabled for protection
*
0xFFFF2000 - r/o (physical overlaps with vectors)
*
0xFFFF2400 - Interrupt stack (1k)
*
0xFFFF2800 - r/o (physical overlaps with Abort stack & FIQ stack)
*
0xFFFF3000 - disabled for protection
*
0xFFFF4000 - r/o (physical memory overlaps with vectors & intr. stack & FIQ stack)
*
0xFFFF4900 - Abort stack (2k - 256 bytes)
*&n
bsp; 0xFFFF5000 - disabled for protection
*
0xFFFF6000 - r/o (physical memory overlaps with vectors & intr. stack)
*
0xFFFF6800 - FIQ stack (256 bytes)
*
0xFFFF6900 - r/o (physical memory overlaps with Abort stack)
*
0xFFFF7000 - disabled
*
0xFFFFC000 - kernel stack
*
0xFFFFC800 - KDataStruct
*
0xFFFFCC00 - disabled for protection (2nd level page table for 0xFFF00000)
*/
typedef struct ARM_HIGH {
ulong
firstPT[4096];
// 0xFFFD0000: 1st level page table
PAGETBL
aPT[16];
// 0xFFFD4000: 2nd level page tables
char
reserved2[0x20000-0x4000-16*sizeof(PAGETBL)];
char
exVectors[0x400];
// 0xFFFF0000: exception vectors
char
reserved3[0x2400-0x400];
char
intrStack[0x400];
// 0xFFFF2400: interrupt stack
char
reserved4[0x4900-0x2800];
char
abortStack[0x700];
// 0xFFFF4900: abort stack
char
reserved5[0x6800-0x5000];
char
fiqStack[0x100];
// 0xFFFF6800: FIQ stack
char
reserved6[0xC000-0x6900];
char
kStack[0x800];
// 0xFFFFC000: kernel stack
struct KDataStruct kdata; &
nbsp;
// 0xFFFFC800: kernel data page
} ARM_HIGH;
其中KDataStruct的结构非常重要而且有意思,有些类似Win32下的PEB结构,定义了系统各种重要的信息:
struct KDataStruct {
LPDWORD lpvTls;
/* 0x000 Current thread local storage pointer */
HANDLE
ahSys[NUM_SYS_HANDLES]; /* 0x004 If this moves, change kapi.h */
// NUM_SYS_HANDLES == 32 : PUBLIC/COMMON/SDK/INC/kfuncs.h
0x004 SH_WIN32
0x008 SH_CURTHREAD
0x00c SH_CURPROC
0x010 SH_KWIN32
0x044 SH_GDI
0x048 SH_WMGR
0x04c SH_WNET
0x050 SH_COMM
0x054 SH_FILESYS_APIS
0x058 SH_SHELL
0x05c SH_DEVMGR_APIS
0x060 SH_TAPI
0x064 SH_PATCHER
0x06c SH_SERVICES
char
bResched;
/* 0x084 reschedule flag */
char
cNest;
/* 0x085 kernel exception nesting */
char
bPowerOff;
/* 0x086 TRUE during "power off" processing */
char
bProfileOn;&nb
sp;
/* 0x087 TRUE if profiling enabled */
ulong
unused;
/* 0x088 unused */
ulong
rsvd2;
/* 0x08c was DiffMSec */
PPROCESS pCurPrc;
/* 0x090 ptr to current PROCESS struct */
PTHREAD pCurThd;
/* 0x094 ptr to current THREAD struct */
DWORD
dwKCRes;
/* 0x098
*/
ulong
handleBase;
/* 0x09c handle table base address */
PSECTION aSections[64]; /* 0x0a0 section table for virutal memory */
LPEVENT alpeIntrEvents[SYSINTR_MAX_DEVICES];/* 0x1a0 */
LPVOID
alpvIntrData[SYSINTR_MAX_DEVICES];
/* 0x220 */
ulong
pAPIReturn;
/* 0x2a0 direct API return address for kernel mode */
uchar
*pMap;
/* 0x2a4 ptr to MemoryMap array */
DWORD
dwInDebugger;
/* 0x2a8 !0 when in debugger */
PTHREAD pCurFPUOwner;
/* 0x2ac current FPU owner */
PPROCESS pCpuASIDPrc;
/* 0x2b0 current ASID proc */
long
nMemForPT;
/* 0x2b4 - Memory used for PageTables */
long
alPad[18];
/* 0x2b8 - padding */
DWORD
aInfo[32];
/* 0x300 - misc. kernel info */
// PUBLIC/COMMON/OAK/INC/pkfuncs.h
0x300
KINX_PROCARRAY
address of process array
0x304
KINX_PAGESIZE
system page size
0x308
KINX_PFN_SHIFT
shift for page # in PTE
0x30c
KINX_PFN_MASK
mask for page # in PTE
0x310
KINX_PAGEFREE
# of free physical pages
0x314
KINX_SYSPAGES
# of pages used by kernel
0x318
KINX_KHEAP
ptr to kernel heap array
0x31c
KINX_SECTIONS
ptr to SectionTable array
0x320
KINX_MEMINFO
ptr to system MemoryInfo struct
0x324
KINX_MODULES
ptr to module list
0x328
KINX_DLL_LOW
lower bound of DLL shared space
0x32c
KINX_NUMPAGES
total # of RAM pages
0x330
KINX_PTOC
&nb
sp;
ptr to ROM table of contents
0x334
KINX_KDATA_ADDR
kernel mode version of KData
0x338
KINX_GWESHEAPINFO
Current amount of gwes heap in use
0x33c
KINX_TIMEZONEBIAS
Fast timezone bias info
0x340
KINX_PENDEVENTS
bit mask for pending interrupt events
0x344
KINX_KERNRESERVE
number of kernel reserved pages
0x348
KINX_API_MASK
bit mask for registered api sets
0x34c
KINX_NLS_CP
hiword OEM code page, loword ANSI code page
0x350
KINX_NLS_SYSLOC
Default System locale
0x354
KINX_NLS_USERLOC
Default User locale
0x358
KINX_HEAP_WASTE
Kernel heap wasted space
0x35c
KINX_DEBUGGER
For use by debugger for protocol communication
0x360
KINX_APISETS
APIset pointers
0x364
KINX_MINPAGEFREE
water mark of the minimum number of free pages
0x368
KINX_CELOGSTATUS
CeLog status flags
0x36c
KINX_NKSECTION
Address of NKSection
0x370
KINX_PWR_EVTS
Events to be set after power on
0x37c
KINX_NKSIG
last entry of KINFO -- signature when NK is ready
/* 0x380 - interlocked api code */
/* 0x400 - end */
}
Win32下可以通过PEB结构定位kernel32.dll的基址,然后通过PE文件结构查找Windows API。在Windows CE下,coredll.dll的作用相当于Win32的kernel32.dll,由于KDataStruct结构开始于0xFFFFC800,偏移0x324的aInfo[KINX_MODULES]是一个指向模块链表的指针,通过这个链表能否找到coredll.dll模块呢?让我们来看一下模块的结构:
// PRIVATE/WINCEOS/COREOS/NK/INC/kernel.h
typedef struct Module {