中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 教育认证 > Macrmedia认证
WindowsCE初探
作者:佚名 时间:2004-06-08 10:35 出处:互连网 责编:chinaitpower
              摘要:WindowsCE初探

  从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 {
  LPVOID   lpSelf;         /* 0x00 Self pointer for validation */
  PMODULE   pMod;          /* 0x04 Next module in chain */
  LPWSTR   lpszModName;      /* 0x08 Module name */
  DWORD    inuse;         /* 0x0c Bit vector of use */
  DWORD    calledfunc;       /* 0x10 Called entry bu
  
  t not exit */
  WORD    refcnt[MAX_PROCESSES]; /* 0x14 Reference count per process*/
  LPVOID   BasePtr;        /* 0x54 Base pointer of dll load (not 0 based) */
  DWORD    DbgFlags;        /* 0x58 Debug flags */
  LPDBGPARAM ZonePtr;        /* 0x5c Debug zone pointer */
  ulong    startip;        /* 0x60 0 based entrypoint */
  openexe_t  oe;           /* 0x64 Pointer to executable file handle */
  typedef struct openexe_t {
  union {
  int hppfs;      // ppfs handle
  HANDLE hf;      // object store handle
  TOCentry *tocptr; &nb
  sp; // rom entry pointer
  };            // 0x64
  BYTE filetype;      // 0x68
  BYTE bIsOID;       // 0x69
  WORD pagemode;      // 0x6a
  union {
  DWORD offset;
  DWORD dwExtRomAttrib;
  };            // 0x6c
  union {
  Name *lpName;
  CEOID ceOid;
  };
  &nb
  sp; // rom entry pointer
  };            // 0x64
  BYTE filetype;      // 0x68
  BYTE bIsOID;       // 0x69
  WORD pagemode;      // 0x6a
  union {
  DWORD offset;
  DWORD dwExtRomAttrib;
  };            // 0x6c
  union {
  Name *lpName;
  CEOID ceOid;
  };         &nb
  sp;  // 0x70
  } openexe_t;
  e32_lite  e32;          /* 0x74 E32 header */
  // PUBLIC/COMMON/OAK/INC/pehdr.h
  typedef struct e32_lite {      /* PE 32-bit .EXE header        */
  unsigned short e32_objcnt;   /* 0x74 Number of memory objects      */
  BYTE      e32_cevermajor; /* 0x76 version of CE built for       */
  BYTE      e32_ceverminor; /* 0x77 version of CE built for       */
  unsigned long  e32_stackmax;  /* 0x78 Maximum stack size         */
  unsigned long  e32_vbase;   /* 0x7c Virtual base address of module   */
  unsigned long&nb
  sp; e32_vsize;   /* 0x80 Virtual size of the entire image  */
  unsigned long e32_sect14rva;  /* 0x84 section 14 rva */
  unsigned long e32_sect14size;  /* 0x88 section 14 size */
  struct info e32_unit[LITE_EXTRA]; /* 0x8c Array of extra info units   */
  struct info {            /* Extra information header block   */
  unsigned long  rva;      /* Virtual relative address of info  */
  unsigned long  size;      /* Size of information block      */
  }
  0x8c  EXP Export table position
  0x94  IMP Import table position
  0x9c  RES Resource table position
  0xa4  EXC Exception table position
  0xac  SEC Security table position
  0xb4  FIX Fixup table position
  } e32_lite, *LPe32_list;
  
  o32_lite  *o32_ptr;        /* 0xbc O32 chain ptr */
  DWORD    dwNoNotify;       /* 0xc0 1 bit per process, set if notifications disabled */
  WORD    wFlags;         // 0xc4
  BYTE    bTrustLevel;      // 0xc6
  BYTE    bPadding;        // 0xc7
  PMODULE   pmodResource;      /* 0xc8 module that contains the resources */
  DWORD    rwLow;         /* 0xcc base address of RW section for ROM DLL */
  DWORD    rwHigh
  
  ;         /* 0xd0 high address RW section for ROM DLL */
  PGPOOL_Q  pgqueue;        /* 0xcc list of the page owned by the module */
  typedef struct _PGPOOL_Q {
  WORD  idxHead;      /* head of the queue */
  WORD  idxTail;      /* tail of the queue */
  } PGPOOL_Q, *PPGPOOL_Q;
  } Module;
  
  模块结构偏移0x08是指向模块名字的指针,偏移0x04指向链表里的下一个模块,通过这个模块名字可以在模块链表里找到我们需要的coredll.dll。而偏移0x7c就是该模块的虚拟基址,偏移0x8c是导出表的相对地址。Windows CE使用的PE结构和Win32是一样,那么有写Win32 shellcode经验的朋友自然会想着从coredll.dll的基址按照PE结构顺藤摸瓜来搜索函数地址。但是我们用EVC实际调试时发现coredll.dll找到的基址是0x01F60000,而这个地址的内存是没有分配的(调试器里都是问号),可以访问的地址是从0x01F61000,这和IDAPro反汇编coredll.dll(从rom文件中dump出来,wince下系统在使用的文件连读的权限都没有)出的起始地址一样。Windows CE可能为了节省内存,没有加载文件最开始的0x1000字节头结构。不过没有关系,因为我们已经从模块结构得到该模块的导出表相对地址,直接从导出表就可以查找函数地址了。
  
  --[ 3. Windows CE演示实例
  
  Ratter/29A的WinCE4.Dust代码可能是为了减少体积,他给出的方法是把要搜索函数的序数索引硬编码到程序里,然后根据导出表的地址定位导出地址表,再用硬编码的序数索引来算出函数地址。这种方法让人感觉挺别扭的,虽然代码减少了,可是通用性可能会打折扣,象编写Win32 shellcode一样通过函数名来搜索的方法可能更通用一些。下面的代码就是实现这样的功能。
  
  ; armasm test.asm
  ; link /MACHINE:ARM /SUBSYSTEM:WINDOWSCE test.obj
  
  CODE32
  
  EXPORT WinMainCRTStartup
  
  AREA .text, CODE, ARM
  
  test_start
  
  ; r11 - base pointer
  test_code_start  PROC
  
  stmdb  sp!, {r0 - r12, lr, pc}
  
  bl  get_export_section
  adr  r2, mb
  bl  lookup_imports
  
  mov  r0, #0
  adr  r1, text
  adr  r2, text
  mov  r3, #0       ; MB_OK
  mov  lr, pc
  mov  pc, r9       ; MessageBoxW
  
  bl  get_export_section
  adr  r2, tp
  bl  lookup_imports
  
  mov  r0, #-1
  mov  r1, #0
  mov  lr, pc
  mov  pc, r9
  
  ; basic wide string compare
  wstrcmp  PROC
  wstrcmp_iterate
  ldrh  r2, [r0], #2
  ldrh  r3, [r1], #2
  
  cmp   r2, #0
  cmpeq  r3, #0
  moveq  pc, lr
  
  cmp  r2, r3
  beq  wstrcmp_iterate
  
  mov  pc, lr
  ENDP
  
  ; output:
  ; r0 - coredll base addr
  ; r1 - export section addr
  get_export_section  PROC
  stmdb  sp!, {r4 - r9, lr}
  
  ldr  r4, =0xffffc800  ; KDataStruct
  ldr  r5
  
  , =0x324    ; aInfo[KINX_MODULES]
  
  add  r5, r4, r5
  ldr  r5, [r5]
  
  ; r5 now points to first module
  
  mov  r6, r5
  mov  r7, #0
  
  iterate
  ldr  r0, [r6, #8]   ; get dll name
  adr  r1, coredll
  bl  wstrcmp    ; compare with coredll.dll
  
  ldreq  r7, [r6, #0x7c]  ; get dll base
  ldreq  r8, [r6, #0x8c]  ; get export section rva
  
  add  r9, r7, r8
  beq  got_coredllbase  ; is it what we're looking for?
  
  ldr  r6, [r6, #4]
  cmp  r6, #0
  cmpne  r6, r5
  bne  iterate    ; nope, go on
  
  got_coredllbase
  mov  r0, r7
  add  r1, r8, r7   ; yep, we've got imagebase
  ; and export section pointer
  
  ldmia  sp!, {r4 - r9, pc}
  ENDP
  
  coredll  DCB  "c", 0x0, "o", 0x0, "r", 0x0, "e", 0x0, "d", 0x0, "l", 0x0, "l", 0x0
  DCB  ".", 0x0, "d", 0x0, "l", 0x0, "l", 0x0, 0x0, 0x0
  
  <
  P>  ; basic string compare
  bstrcmp  PROC
  bstrcmp_iterate
  ldrb  r9, [r7], #1
  ldrb  r10, [r8], #1
  
  cmp   r9, #0
  cmpeq  r10, #0
  moveq  pc, lr
  
  cmp  r9, r10
  beq  bstrcmp_iterate
  
  mov  pc, lr
  ENDP
  
  ; r0 - coredll base addr
  ; r1 - export section addr
  ; r2 - function name addr
  lookup_imports  PROC
  stmdb  sp!, {r4 - r6, lr}
  
  ldr  r4, [r1, #0x20]  ; AddressOfNames
  add  r4, r4, r0
  
  mov  r6, #0       ; counter
  lookup_imports_iterate
  ldr  r7, [r4, #4]!
  add  r7, r7, r0     ; function name ponter
  mov  r8, r2       ; find function name
  
  bl   bstrcmp
  
  addne r6, r6, #1
  bne  lookup_imports_iterate
  
  add  r6, r6, r6
  ldr  r5, [r1, #0x24]  ; AddressOfNameOrdinals
  add  r5, r5, r0
  ldrh  r9, [r5, r6]    ; Ordinals
  ldr  r
  
  6, [r1, #0x10]  ; ordinal base
  add  r9, r9, r6
  ldr  r5, [r1, #0x1c]  ; AddressOfFunctions
  add  r5, r5, r0
  ldr  r9, [r5, r9, LSL #2] ; function address rva
  add  r9, r9, r0     ; function address
  
  ldmia  sp!, {r4 - r6, pc}
  ENDP
  
  mb  DCB   "MessageBoxW", 0x0
  tp  DCB   "TerminateProcess", 0x0,0x0,0x0,0x0
  ALIGN  4
  
  ; Dear User, am I allowed to spread?
  
  text DCB  "H", 0x0, "e", 0x0, "l", 0x0, "l", 0x0, "o", 0x0, " ", 0x0
  DCB  "W", 0x0, "i", 0x0, "n", 0x0, "C", 0x0, "E", 0x0, "!", 0x0
  DCB  0x0, 0x0, 0x0, 0x0
  ALIGN  4
  
  LTORG
  test_end
  
  ; the code after test_end doesn't get copied to victims
  
  WinMainCRTStartup PROC
  b   test_code_start
  ENDP
  
  ; first generation entry point
  host_entry
  mvn  r0, #0
  mov  pc, lr
  END
  
  代码还是比较傻,如果能把Win32 shellcode的hash引入可能代码会更好看一些。Ratter/29A在WinCE4.Dust虽然还只是个概念病毒,但是病毒的基本技术它都已经具备了,所以不难相信不久就会有更多的Windows CE病毒。如果作者不怀好意,用KernelIoControl把系统引导入BootLoader模式,那么对于很多非专业的用户来说无疑象遭遇CIH病毒一般可恶。
  
  通过上面的代码不难相信很容易就能写出Windows CE下的shellcode,Seth Fogie在最近的defcon等会议上提到Windows CE下缓冲区溢出,随着PDA网络化程度越来越高,以及和手机的结合,相信Windows CE下的缓冲区溢出不久就会流行起来。不过Windows CE下缓冲区溢出可能会遭遇几个问题:
  
  1. Windows CE是一个Unicode环境,它可能会把用户输入的数据转成Unicode格式。
  2. 要在Windows CE上写解码shellcode可能会有些问题,首先arm没有xor指令,另外还有可能遭遇指令缓存的问题。不是很清楚Windows CE对软中断指令swi怎么支持。
  3. 不同厂商不同版本的PDA可能存在这样那样的差异,导致攻击程序无法通用。
  
  不过Windows CE现在已经发展的很成熟了,可以进来看看。
关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有