Posted June 25, 200916 yr Hi guys. It's me again, with another kinky weird request from y'allz. Do you happen to know the fastest way to clear all registers? (e-a-c-d-b-x, e-s-d-i)I wrote something like this, keeping in mind I want code to be small:_WIPE proc push 6h pop ecx @loop: push 0 loop @loop pop eax pop ecx pop edx pop ebx pop esi pop edi ret_WIPE endpPretty much looks like a Delphi function in prolog, lol. Post your thoughts, please!
June 25, 200916 yr What about that one (makes assumptions concerning the stack, you should mind zeroing it manually via rep movsd)? sub esp, 0x20mov dword ptr [esp - 0x0c], espsub dword ptr [esp - 0x0c], 0x20popadedit: Didn't save ebp though you intended to keep it as well, try that one:mov dword ptr [esp - 0x18], ebpmov dword ptr [esp - 0x14], espsub esp, 0x20popad Edited June 25, 200916 yr by metr0
June 25, 200916 yr Author Actually, I will modify my function with this :-)_WIPE procpush 6hpop ecx@loop:push 0loop @looppopad // :-)))ret_WIPE endpEDIT: Didn't know ESP and EBP are also pushed to stack on a PUSHAD o_O Edited June 25, 200916 yr by SunBeam
June 25, 200916 yr Keep in mind you're pushing six zero dwords, though popping eight values from the stack. Plus, you zero ebp and esp, not sure if you want to save them?
June 25, 200916 yr Author Yeah, I did PUSH 8. And It wiped all but ESP on a POPAD.. Thing is I want to keep ESP and EBP from being emptied.. Edited June 25, 200916 yr by SunBeam
June 25, 200916 yr Hi,You want fastest or smallest method ?Because loops are never fast ...XOR -> 1 ClockPUSH+POP -> 1+1 = 2 ClocksXOR wins
June 25, 200916 yr Author Smallest I meant, my bad :-) The smallest code possible.. Or, how to say this, the most COMPACT method that can be written in a few lines (2-3 lines if possible)..P.S.: Wish there was a CASE option for registers, LOL. Like:--push 4hpop ecx@loop_1:push 0loop @loop_1@loop_2:case (a..d) X:pop eXxloop @loop_2Looks like crap, but wish there was something like that :-) Or..eAx -> inc "A" == B -> eBx -> inc "B" == C -> eCx .. Edited June 25, 200916 yr by SunBeam
June 26, 200916 yr Author Just wanted to add Peter's trick is pretty neat :-) Here's a little glimpse:
June 26, 200916 yr :-) If, for some reason, the FPU were in use, then you can do it in a really obvious way:push 0pop eaxpush eaxpush eaxpush eaxpush eaxpush eaxpush ebppush eaxpush eaxpopadbut it's 12 bytes and lots of lines. FPU will be empty on process start because the context is set that way.
June 26, 200916 yr Author I had to hit the exception from the rule, Peter. Here's the source code: .586p.mmx .model flat, stdcalloption casemap :noneinclude \masm32\include\windows.incinclude \masm32\include\user32.incinclude \masm32\include\kernel32.incinclude \masm32\include\masm32.incinclude \masm32\include\comctl32.incinclude \masm32\macros\macros.asmincludelib \masm32\lib\user32.libincludelib \masm32\lib\kernel32.libincludelib \masm32\lib\comctl32.libincludelib \masm32\lib\masm32.lib.databText db "Result: ",0.data?bSpot dd ?.codeRegWipe proc push ebp pushad fnsave [esp-4ch] popad pop ebp retRegWipe endpDisplay proc fn lstrcpy, addr bSpot, hex$(ebx) fn lstrcat, addr bText, addr bSpot fn MessageBox, 0, addr bText, "Boing!", MB_OK OR MB_ICONINFORMATION fn RtlZeroMemory, addr bText+0Ah, 10h retDisplay endpFuncA proc mov AX,171 sub AX,154 mov CX,AX shl AX,2 sub AX,CX mov BL,AL call Display call RegWipe retFuncA endpFuncB proc mov BX,101 mov CL,42h sub BX,13h shr CX,1 sub BL,CL call Display call RegWipe retFuncB endpFuncC proc mov AX,13h mov BX,3 mul BL mov BL,AL call Display call RegWipe retFuncC endpFuncD proc mov CX,7 mov AX,0C8h idiv CL add AL,01Bh mov BL,AL call Display call RegWipe retFuncD endpFuncE proc mov CX,12h sub CX,0Ah shl CX,1 mov BX,CX shl CX,2 add CX,BX sub CL,5 mov BL,CL call Display call RegWipe retFuncE endpmain proc fn InitCommonControls call RegWipe call FuncA call FuncB call FuncC call FuncD call FuncE @end: retmain endpend main Main RegWipe caller: FPU state before calling RegWipe inside FuncA: And afterwards :-( Kinda owned me :-)
June 26, 200916 yr You don't seem to load any wicked DLL.. anyway wanted to mention it. I once tried using FPU and MMX at the same time lol, so I remember them using the same REGs.Just import any DLL which uses for instance mmx stuff in its init code or whatever.. and there you go.. f* up FPU REGs ^^
June 27, 200916 yr It might also be Olly parsing something and changing the context.You can add a fninit before the wipe. It adds only two bytes, and guarantees that the context is clean, at least at that moment.There's also the possibility that single-stepping will give you a different result from just running directly (I know of an FPU-related single-step vs run anti-debugging trick, but this isn't it).Also inside vs outside of a debugger. Could be a nice anti-debugging trick, if that is the case. ;-)
June 27, 200916 yr You could do this, which is a slight modification to just XORing all the registers.XOR ECX,ECXMUL ECXXOR EBX,EBXXOR ESI,ESIXOR EDI,EDIIt's only 10 bytes and eveything else is preserved.Sub Xero
June 27, 200916 yr Author ^ Good one ;-) And the FINIT thingie didn't do the trick. Plus it happens both in Olly and outside of it, so it's not a debugger-only behavior.P.S.: Had a little typo in the source above:fn RtlZeroMemory, addr bText+08h, 8h // fixed Edited June 27, 200916 yr by SunBeam
July 14, 200916 yr I prefer ClearRegs! ClearRegs MACRO .data zer dd 0,0,0,0,0,0,0,0, zer .code xchg esp, [zer+8*4] popad pop esp ENDM ClearRegs1 MACRO push 32 pop ecx sub esp, ecx mov edi, esp xor eax, eax rep stosb popad ENDM
July 15, 200916 yr To be honest, unless you have this in a loop (read: bruteforce) you wont notice the difference. If this was used in something which was time critical and was being executed millions of times, then you'd worry about clock cycles, latency and how well you can fit instructions in the pipeline to take advantage of OOE (out of order execution).If you have a small loop that is executed many times, where the code is small enough to fit into the L1 cache, then you'll notice a difference, but otherwise most options to clear your registers will execute in a nanosecond anyway.The MASM32 forum is a good place for information about instruction speeds, etc.HR,Ghandi
August 6, 200916 yr Author @ghandi: This isn't about speed, but about SHORTER ways to do it (smaller code)@ksbunker: Didn't know of one such macro. It's written by yourself?@av999: Will try that one out. Feedback soon enough..EDIT1: av999, any way to preserve EBP as well?EDIT2: Did something like this...dataszPtr dd szStuff.data?szStuff dd 20h dup(0)RegWipe PROC xchg dword ptr ds:[szPtr],esp popad xchg dword ptr ds:[szPtr],esp mov ebp,esp add ebp,4 retRegWipe ENDP Edited August 6, 200916 yr by SunBeam
Create an account or sign in to comment