Log in

View Full Version : Need help figuring out code from unpacker.


WaxfordSqueers
January 25th, 2005, 20:23
Howdy,

The code below comes from an Asprotect packed file. Values to the right of the <<<< signs was added by me based on the value in each register. It seems to be a check of some kind involving the CPUID instruction. I can follow it to a certain extent, but the following questions arise:

1)what is this piece of code doing? Upon return from the CPUID instruction, the AH, AL reg is manipulated to get 0F. That value is compared to 03 at 408B08, after the return. The return code is right below the main body. There's a branch there that I suspect is a good guy/bad guy thing.


2) Is there a way in softice to see the entire flag register?

It seems to me bit 21 on the flags reg is checked by way of an XOR to see if CPUID is supported. Also, bit 18 is checked for alignment. It's possible other flags are being manipulated that I can't see out of inexperience. It would be nice to watch them as it happened.

BTW...I have Iceext loaded (XP with SP2 and Ice 4.3.1) with full protection on. It does such a good job that even symbol loader can't find softice. :-) Setting byte one of the unhandledexceptionfilter code to 90, dynamically in memory, before Iceext loads, allows all the hiding features of Iceext to come on. It replaces the NOP with 68, but it doesn't seem to want to load that protection otherwise if Softice grabs it with a CC first.

3)there's a POPFD instruction at 408AC3 that adds the value in the stack to the value in the EAX register. How does that work? Before the POPFD, the EAX was 0x00000003. After the POPFD, it was 40206, and the POPFD value was 40202. Can POPFD add to a value in a register? I don't see that in any Intel literature. I can't see anything that would have altered the flags from the time they were pushed and re-popped, unless the XOR at 408ABA altered the parity and auxiliary flag, or something.

00408AA4 53 push ebx
00408AA5 51 push ecx
00408AA6 52 push edx
00408AA7 89 E3 mov ebx, esp
00408AA9 83 E4 FC and esp, 0FFFFFFFCh
00408AAC 9C pushfd <<<<<<<<00000202
00408AAD 9C pushfd <<<<<<<<00000202
00408AAE 58 pop eax <<<<<00000202
00408AAF 89 C1 mov ecx, eax <<<<ECX= 00000202
00408AB1 35 00 00 04 00 xor eax, 40000h <<<0040202
00408AB6 50 push eax <<<<0040202
00408AB7 9D popfd
00408AB8 9C pushfd
00408AB9 58 pop eax <<<<40202
00408ABA 31 C8 xor eax, ecx <<<EAX=40000 after the XOR
00408ABC B8 03 00 00 00 mov eax, 3 <<<EAX = 00000003
00408AC1 74 24 jz short loc_408AE7
00408AC3 9C pushfd
00408AC4 58 pop eax <<<<0040206
00408AC5 89 C1 mov ecx, eax
00408AC7 35 00 00 20 00 xor eax, 200000 <<<<240206h
00408ACC 50 push eax <<<<240206
00408ACD 9D popfd
00408ACE 9C pushfd
00408ACF 58 pop eax <<<<204026
00408AD0 31 C8 xor eax, ecx <<<EAX=200000 (ECX was 40206)
00408AD2 B8 04 00 00 00 mov eax, 4 <<<EAX=4
00408AD7 74 0E jz short loc_408AE7
00408AD9 53 push ebx <<<<12FF68
00408ADA B8 01 00 00 00 mov eax, 1
00408ADF 0F A2 cpuid <<<<ret EAX=F27; EBX=1080A;
ECX=4400;EDX=BFEBFBFF

00408AE1 88 E0 mov al, ah <<<eax=0000000F
00408AE3 83 E0 0F and eax, 0Fh
00408AE6 5B pop ebx
00408AE7
00408AE7 loc_408AE7:
00408AE7 ; sub_408AA4+33j
00408AE7 9D popfd
00408AE8 89 DC mov esp, ebx
00408AEA 5A pop edx
00408AEB 59 pop ecx
00408AEC 5B pop ebx
00408AED C3 retn to 408B03


00408B03 mov ds:dword_413098, eax
00408B08 cmp ds:dword_413098, 3 <<<<<cmp F to 3.
00408B0F jle short loc_408B26
00408B11 mov ds:dword_413090, offset loc_4046B8
00408B1B mov ds:dword_413094, offset loc_4046D8
00408B25 C3 retn

WaxfordSqueers
January 25th, 2005, 22:51
Quote:
[Originally Posted by WaxfordSqueers]1)what is this piece of code doing? Upon return from the CPUID instruction, the AH, AL reg is manipulated to get 0F. That value is compared to 03 at 408B08, after the return. The return code is right below the main body. There's a branch there that I suspect is a good guy/bad guy thing.


Kind of bad when I answer my own question.

Crusader advised that people read through the Asprotect dll he went to so much trouble to create. I finally did and see now that the code above comes early near the initialization part of the dll. So, it may be legit. If one of you code gurus has the time or inclination, could you have a peek at it anyway to confirm that it's harmless? I'm getting paranoid about SEH's and anti-ice tricks.

I wouldn't mind an answer to the POPFD mystery and to whether there's more info available on the hidden flags in softice.

If this is taking up too much room, please delete it. And thanks again Crusader for all your work on Asprotect.

upb
January 26th, 2005, 01:56
the pushfd \ pop \ xor \ push \popfd sequences flip a flag each time.
but im not @ home atm so check the intel manual about the structure of EFLAGS register to find out what flags it is flipping.
hope this helps.

bilbo
January 26th, 2005, 03:41
Hi, WaxfordSqueers,

Quote:
[Originally Posted by WaxfordSqueers]I finally did and see now that the code above comes early near the initialization part of the dll. So, it may be legit.


You got it!
The code simply checks for the Processor family. Look!

Code:

; save registers on stack
00408AA4 53 push ebx
00408AA5 51 push ecx
00408AA6 52 push edx

; save stack pointer into EBX
00408AA7 89 E3 mov ebx, esp

; align stack pointer to long (not necessary IMHO: already aligned!)
00408AA9 83 E4 FC and esp, 0FFFFFFFCh

; save EFLAGS on stack
00408AAC 9C pushfd <<<<<<<<00000202

; 386 processor check follows:
; the AC bit (bit #18 in EFLAGS) was introduced
; on the 486 processor: this bit cannot be set on the Intel386 processor
;
; save first EFLAGS snapshot into EAX and ECX

00408AAD 9C pushfd <<<<<<<<00000202
00408AAE 58 pop eax <<<<<00000202
00408AAF 89 C1 mov ecx, eax <<<<ECX= 00000202

; flip the AC bit into EFLAGS
00408AB1 35 00 00 04 00 xor eax, 40000h <<<0040202
00408AB6 50 push eax <<<<0040202
00408AB7 9D popfd

; get a second snapshot of EFLAGS into EAX
00408AB8 9C pushfd
00408AB9 58 pop eax <<<<40202

; compare the two EFLAGS snapshots
00408ABA 31 C8 xor eax, ecx <<<EAX=40000 after the XOR

; if the two snapshot are same (386 processor), return 3 for 386
00408ABC B8 03 00 00 00 mov eax, 3 <<<EAX = 00000003
00408AC1 74 24 jz short loc_408AE7

; 486 processor check:
; check for the ability to set/clear ID flag (Bit 21 in EFLAGS)
; which indicates support for the CPUID instruction (Pentium)
;
; save first EFLAGS snapshot into EAX and ECX

00408AC3 9C pushfd
00408AC4 58 pop eax <<<<0040206
00408AC5 89 C1 mov ecx, eax

; flip the ID bit into EFLAGS
00408AC7 35 00 00 20 00 xor eax, 200000 <<<<240206h
00408ACC 50 push eax <<<<240206
00408ACD 9D popfd

; get a second snapshot of EFLAGS into EAX
00408ACE 9C pushfd
00408ACF 58 pop eax <<<<204026

; compare the two EFLAGS snapshots
00408AD0 31 C8 xor eax, ecx <<<EAX=200000 (ECX was 40206)

; if the two snapshot are same (486 processor), return 4 for 486
00408AD2 B8 04 00 00 00 mov eax, 4 <<<EAX=4
00408AD7 74 0E jz short loc_408AE7

; save EBX on stack
00408AD9 53 push ebx <<<<12FF68

; issue CPUID with argument 1:
; return version information into EAX

00408ADA B8 01 00 00 00 mov eax, 1
00408ADF 0F A2 cpuid <<<<ret EAX=F27

; insulate and return family into EAX (0FH for Pentium 4 Processor Family)
00408AE1 88 E0 mov al, ah <<<eax=0000000F
00408AE3 83 E0 0F and eax, 0Fh

; restore EBX from stack
00408AE6 5B pop ebx

; return EAX
00408AE7 loc_408AE7:
; restore flags from stack
00408AE7 9D popfd

; restore stack pointer from EBX
00408AE8 89 DC mov esp, ebx

; restore registers from stack
00408AEA 5A pop edx
00408AEB 59 pop ecx
00408AEC 5B pop ebx
00408AED C3 retn to 408B03


00408B03 mov ds:dword_413098, eax ; Family

00408B08 cmp ds:dword_413098, 3 <<<<<cmp F to 3.
; jump if processor is less/equal 386
00408B0F jle short loc_408B26

00408B11 mov ds:dword_413090, offset loc_4046B8
00408B1B mov ds:dword_413094, offset loc_4046D8
00408B25 C3 retn


Best regards, bilbo

WaxfordSqueers
January 26th, 2005, 17:36
Quote:
[Originally Posted by bilbo]Hi, WaxfordSqueers,You got it!
The code simply checks for the Processor family. Look!


thanks for the analysis Bilbo, very helpful. At first, I thought they might be checking for the trap flag, to see if I was single-stepping, but I was being a little too paranoid.

I made a mistake when analyzing the flags register. From the diagram of the register in the Intel manual, it shows the flags listed from 0 to 31. There are positions between cf and pf, pf and af and af and zf that are reserved slots for the system. The 1,3 and 5 slots seem to be permanently set to 1, 0 and 0 respectively. I was calculating my numbers based on what I saw in softice rather than what is actually in the flags reg.

Based on the Intel manual, the 4 LSB's are as follows:

0 pf 1 cf
3 2 1 0 <<<<LSB's

with slots 1 and 3 permanently set. With cf=pf=0, that would give the 2 in 202. Obviously, then, the pf flag was turned on by the XOR statement immediately before the 0x00000003 was loaded into EAX. That would set the 4 LSB's to 0110, giving the 40206 value.

BTW, Intel describes the action of XOR as follows:

The OF and CF flags are cleared; the SF, ZF, and PF flags are set according to the result. The state of the AF flag is undefined.

That clears that mystery, but I'm still wondering if there is a way to examine the entire flags register in softice.

thanks again for your input Bilbo.

Kayaker
January 26th, 2005, 19:47
Quote:
[Originally Posted by WaxfordSqueers]
That clears that mystery, but I'm still wondering if there is a way to examine the entire flags register in softice.

Yes, the CPU command, check the EFL output lines. Only the flags Sice cares about are listed, but you could do a bit check on the rest. Interestingly Not responsive to manual changing of the flags with R FL x.

Huh, that was interesting Middle Earth lore. If I ever do a processor check I'll use that code

JMI
January 26th, 2005, 23:12
Yes sir, that wandering Hobbit has discovered some interesting lore in his travels.

Regards,

WaxfordSqueers
January 27th, 2005, 00:29
Quote:
[Originally Posted by Kayaker]Yes, the CPU command, check the EFL output lines. Only the flags Sice cares about are listed, but you could do a bit check on the rest. Interestingly Not responsive to manual changing of the flags with R FL x.


Thanks Kayaker. I looked at the CPU command, but obviously not closely enough.

Before I got sane and bought my P4 processor, I was looking at a way to run a P3 at 1.3 gigs on a 440BX motherboard (designed for P2 at about 300Mhz). It was being done by rewiring the processor socket and isolating pins on the processor itself. If they wont let us at the flags, etc., we may have to go that route. I don't think we have a forum for reversing-related hardware mods on this board, do we?

WaxfordSqueers
January 27th, 2005, 00:40
Quote:
[Originally Posted by JMI]Yes sir, that wandering Hobbit has discovered some interesting lore in his travels. Regards,


Travelling can be a good Habbit.

bilbo
January 27th, 2005, 02:38
Thanks, humans, for your appreciations...

in fact I travelled the net...
http://www.google.com/search?q=cpuid.asm+intel

best regards, bilbo

JMI
January 27th, 2005, 10:35
That's also good traveling and good lore.

Regards,

WaxfordSqueers
January 27th, 2005, 18:29
Quote:
[Originally Posted by bilbo]Thanks, humans, for your appreciations...in fact I travelled the net...http://www.google.com/search?q=cpuid.asm+intelbest regards, bilbo


Hey Bilbo...I'm sure you are aware of the free set of reference manuals at Intel:

http://www.intel.com/design/pentium4/manuals/index_new.htm

bilbo
January 28th, 2005, 02:35
Thanks, WaxfordSqueers
I have a local copy of them and I use them many times in a month...
Maybe the link should be put at the end of this Board, isn't it?

Best regards, bilbo