Log in

View Full Version : trouble with asprotect


homersux
June 22nd, 2005, 15:03
I've been reading tuts and done my homework on asprotect. I am a little confused the way seh works in olly (btw, the target is ASProtect v1.23 RC1 reported by voyerpe or ASProtect 1.2x - 1.3x [Registered] -> Alexey Solodovnikov by peid 0.93) Please send me a PM if you are interested in examing the target. I have tried various ways but so far I can't figure this thing out. I've even tried unpackers and none of them works on this seemingly easy target. One more note, this application is developped by a hacker and possibly the 1.23 rc1 sdk was used in this particular release.


009FE1F0 893B MOV DWORD PTR DS:[EBX],EDI <-- exception
009FE1F2 56 PUSH ESI
009FE1F3 F7D7 NOT EDI
009FE1F5 DF57 64 FIST WORD PTR DS:[EDI+64]
009FE1F8 51 PUSH ECX
009FE1F9 FB STI

0012FF28 0012FF80 Pointer to next SEH record
0012FF2C 009FE0C8 SE handler
0012FF30 00A8E798

009FE0C8 51 PUSH ECX
009FE0C9 81F1 0AAF16E5 XOR ECX,E516AF0A
009FE0CF 334C24 08 XOR ECX,DWORD PTR SS:[ESP+8]
009FE0D3 334C24 28 XOR ECX,DWORD PTR SS:[ESP+28]
009FE0D7 8D4C24 41 LEA ECX,DWORD PTR SS:[ESP+41]


this is one example how i track the SEH, here is the last access violation:


009FFAA5 C700 EFCA5C85 MOV DWORD PTR DS:[EAX],855CCAEF
009FFAAB 67:64:8F06 0000 POP DWORD PTR FS:[0]
009FFAB1 83C4 04 ADD ESP,4
009FFAB4 83E8 AF SUB EAX,-51
009FFAB7 83C8 4B OR EAX,4B
009FFABA 58 POP EAX

0012FF34 0012FF80 Pointer to next SEH record
0012FF38 009FFA6E SE handler
0012FF3C E850D8BF

009FFA6E 56 PUSH ESI
009FFA6F F2: PREFIX REPNE: ; Superfluous prefix
009FFA70 EB 01 JMP SHORT 009FFA73
009FFA72 F0:037424 38 LOCK ADD ESI,DWORD PTR SS:[ESP+38] ; LOCK prefix is not allowed
009FFA77 C1DE 83 RCR ESI,83 ; Shift constant out of range 1..31
009FFA7A 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10]
009FFA7E 8D76 52 LEA ESI,DWORD PTR DS:[ESI+52]
009FFA81 8346 66 06 ADD DWORD PTR DS:[ESI+66],6
009FFA85 8D7475 6F LEA ESI,DWORD PTR SS:[EBP+ESI*2+6F]
009FFA89 83EE 6F SUB ESI,6F
009FFA8C 5E POP ESI
009FFA8D 83C8 FF OR EAX,FFFFFFFF
009FFA90 40 INC EAX
009FFA91 C3 RETN


At this exception, I put a break point on 009ffa6e. Instead of shift+f9, i use shift+f7 to single step into ntdll exception unwind sub,


7C90EAF0 8B1C24 MOV EBX,DWORD PTR SS:[ESP]
7C90EAF3 51 PUSH ECX
7C90EAF4 53 PUSH EBX
7C90EAF5 E8 C78C0200 CALL ntdll.7C9377C1
7C90EAFA 0AC0 OR AL,AL
7C90EAFC 74 0C JE SHORT ntdll.7C90EB0A
7C90EAFE 5B POP EBX
7C90EAFF 59 POP ECX
7C90EB00 6A 00 PUSH 0
7C90EB02 51 PUSH ECX
7C90EB03 E8 11EBFFFF CALL ntdll.ZwContinue

at the last instruction, i use f7 to follow into ZwContinue and after some more f7, i get to

7C90EB8B > 8BD4 MOV EDX,ESP
7C90EB8D 0F34 SYSENTER
7C90EB8F 90 NOP
7C90EB90 90 NOP
7C90EB91 90 NOP
7C90EB92 90 NOP
7C90EB93 90 NOP
7C90EB94 > C3 RETN


Notice the sysenter? well at this point, when I f7 on sysenter, the protected program simply starts running and left olly in the dust. I am wondering what I did wrong here? Maybe it's the 2nd chain in the seh? But why the seh handler is not invoked? Really confused here.

blabberer
June 23rd, 2005, 04:21
i dont know squat about armadillo or asprotect
but i know if you f7 into sysenter of ZwContinue it will execute without stopping
so how do you know where it will execute the next instruction
when you are on ZwContinue
ie on this instruction
7C90EB8B > 8BD4 MOV EDX,ESP

and if you are using ollydbg look into stack there you will see the the context structure being pushed for ZwContinue
IN PCONTEXT ThreadContext,

right click follow in dump from stack
you should see some weird little charecters count 0xb8 from the start
you will see a dword which is eip of the next instruction that will be executed
click on cpu pane press ctrl+g type the address you just found (keep in mind endian some crap ie reverse and type the correct address)and hit enter olly will take you to that address

press f2 on that address and f9 f8 or f7 whatever the system will land you right on that instruction

this holds true for any and every seh that gets continued

ok here is some paste i m using w2k so its int 2e for me not sysenter ok but functionally both are almost same (well sysenter is faster they say i dont have conters to corraborate or contradict it )

[CODE]
77F82881 ZwContinue MOV EAX,1C
77F82886 LEA EDX,DWORD PTR SS:[ESP+4]
77F8288A INT 2E
77F8288C JMP ntdll.77F99D23

the stack as follows
ESP ==> > 77F9FF7C RETURN to ntdll.77F9FF7C from ntdll.ZwContinue
ESP+4 > 0012F940 <-- select right click follow in dump
if you count 0xb8 from this you will land here
0012F9F0 08 06 41 00 A.

now 410608 is the next eip
if it was analysed and valid place you can even stop doing ctrl+g but select the address right click and do follow in disassembler
olly will take you directly to the address
00410608 DIV CL

or better still when you are in stack you can type [esp+4]+0xb8 and hit enter
olly should take you right to your next eip

or still better hit alt+f1 and get the commandline plugin out
type
at ds:[[esp+4]+0xb8] and olly will take you to the next eip


[edit]
oh btw i did not read fully when you are on ZwContinue the handler has already been called and it has done its thingamagic you are asking why handler is not executed ??? have you gone through the sequence

when you hit shift+f7 on exception you will land in ntdll and
this is the sequnce of events that happen
rtlpGetStackLimits
rtlp some craps

and finally it reaches ExecuteHandler() which is always
a call near ecx
that calls your seh handler only when you handler returned continuable
you will reach the ZwContinue() else it will directly go to ZwRaiseException and crash out
so if you say you are on ZwContinue that means you handler has been executed and it returned Continuable as return

homersux
June 23rd, 2005, 07:13
blabberer, thanks for your reply. My confusion is exactly why the seh handler isn't being called.

Quote "that calls your seh handler only when you handler returned continuable
you will reach the ZwContinue() else it will directly go to ZwRaiseException and crash out
so if you say you are on ZwContinue that means you handler has been executed and it returned Continuable as return"

I am confused, so when I reach ZwContinue(), is the seh handler executed? Who is returning continuable? I thought seh handler returns continuable.

blabberer
June 23rd, 2005, 07:50
yes if you are on ZwContinue the seh handler should have been executed
and your handler retuned continuable else it wouldnt have reached ZwContinue at all
it would have gone Directly to ZwRaiseException (mostly crash dialog)

when there is an exception
77F9FF60 KiUserExceptionDispatcher
is called if you press shift f7 or shift f8 or shift f9
which
chandles the Executehandler and either calls ZwContinue or ZwRaiseException

Code:

77F9FF60 KiUserExceptionDispatch>MOV ECX,DWORD PTR SS:[ESP+4]
77F9FF64 MOV EBX,DWORD PTR SS:[ESP]
77F9FF67 PUSH ECX
77F9FF68 PUSH EBX
77F9FF69 CALL ntdll.77F96BDD < this is the call which calls the handler if you single step through it you will always find a
call near ecx or call near eax or call near r32 that is the call that actually
executes the handler
77F9FF6E OR AL,AL <---- here is the comparison
77F9FF70 JE SHORT ntdll.77F9FF7E
77F9FF72 ---->POP EBX <-----go here
77F9FF73 POP ECX
77F9FF74 PUSH 0
77F9FF76 PUSH ECX
77F9FF77 CALL ntdll.ZwContinue
77F9FF7C JMP SHORT ntdll.77F9FF89
77F9FF7E ----->POP EBX <--- or go here
77F9FF7F POP ECX
77F9FF80 PUSH 0
77F9FF82 PUSH ECX
77F9FF83 PUSH EBX
77F9FF84 CALL ntdll.ZwRaiseException


what is your doubt ??

homersux
June 23rd, 2005, 08:26
I did put a breakpoint on the seh handler entry point before I shift+f7 into the ntdll subroutines. If it's already executed, my question as I stated, why isn't the breakpoint taken in the seh handler?

009FFAA5 C700 EFCA5C85 MOV DWORD PTR DS:[EAX],855CCAEF
009FFAAB 67:64:8F06 0000 POP DWORD PTR FS:[0]
009FFAB1 83C4 04 ADD ESP,4
009FFAB4 83E8 AF SUB EAX,-51
009FFAB7 83C8 4B OR EAX,4B
009FFABA 58 POP EAX

0012FF34 0012FF80 Pointer to next SEH record
0012FF38 009FFA6E SE handler
0012FF3C E850D8BF

009FFA6E 56 PUSH ESI <---I am supposed to break here but I didn't
009FFA6F F2: PREFIX REPNE: ; Superfluous prefix
009FFA70 EB 01 JMP SHORT 009FFA73

Some thoughts on olly
1) Wish the speicial menu in dump window has more option other than pe header, for example, a exception context record would be handy
2) For some wierd reason I cann't change eip in olly. double click eip or
the eip address doesn't do anything unlike the other common registers. And 'r eip xxxxxxxx' doesn't work either. How do you change eip in olly?

blabberer
June 23rd, 2005, 09:12
does that address you put your break point match with the top most handler ??
one can chain 1000s of handler one below another and every one of those handler would get a chance to put its finger in the pie
the handler you put break point seems to be from stack
may be you could match it with view --> seh chain --> follow handler ???
also have you considered the possibilty that some one may be changing the
next seh handler from the prior handler ??

well you can use labeller plugin to label a struct and apply it and use long --> addr with ascii dump format

as to changing eip it is simply right click new origin here or global short cut
ctrl+ *

homersux
June 23rd, 2005, 12:10
blabberer, thanks for the nice olly tips. labeller is really nice. however ctl+* or right click new origin doesn't work for me, hehe. Olly1.10+winxp sp2 here. I wonder why I can't change eip.

blabberer
June 23rd, 2005, 12:56
what do you mean doesnt work ??
as far as i can say it works in all os > 95 < to be released
you should select th line where you want to change the control to
and hit ctrl+* or right click on that line and hit new origin here
if you are changing your eip to some data area ollydbg even warns about disastarous consequences and asks you to confirm if you really want to
change your eip
btw that labeller plugin has some divide by zero bug that could crash ollydbg
so use it with care ( if you define some dword or byte in your struct and it isnt handling that keyword it sets the size of to 0 and becuse of that it crashes )
and i dunno if the author is still working with it he doesnt reply back to mails

and also you could fetch the symbols for all basic dlls and put it in ollydbg dir so that you get a good view of all the call names
so that instead of call 77f81234
you can see rtlpExecuteHandlerforException()
also all other names viz KiUserDispatchException()
rtlpGetStacklimits()
rtlpGetblah blah blah

actually it is more fun to poke inside system like you do and zero in on weakness or find places to decieve these reverser wearing tactics

homersux
June 23rd, 2005, 13:24
ahh, I figured it out, I am using a laptop and it does not have 'Grey *'. The popup menu works. I didn't realize that. The exception context trick works pretty well. labeler does not really put anything in the long->addr ascii dump comment window. Here is a snippet of the context struct:

struct FLOATMMX {
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
BYTE FPREGS[80];
DWORD CR0;
};

struct CONTEXT {
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
BYTE FLOATMMX[128];
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
};

how do you fetch dll symbols? I probably should hit the search button now. damn it's hard to convert from sice to olly.

blabberer
June 23rd, 2005, 13:30
wellyou have to instance them and the instances will be labelled
i mean dword eax eax some thing i cant paste one of my struct right now
but i have structs for all in the labellers file in ollydbg (actually you can take a look a teh defaulr msg stuct that is defined in there

ah search engine
ok here is a link
take a look a the patch and other relevent details
like srv* path
hxxp://ollydbg.win32asmcommunity.net/?action=vthread&forum=1&topic=679

edit xx to tt
have fun

homersux
June 23rd, 2005, 14:44
7C9377C1 > 8BFF MOV EDI,EDI
7C9377C3 55 PUSH EBP
7C9377C4 8BEC MOV EBP,ESP
7C9377C6 83EC 64 SUB ESP,64
7C9377C9 56 PUSH ESI
7C9377CA FF75 0C PUSH DWORD PTR SS:[EBP+C]
7C9377CD 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
7C9377D0 56 PUSH ESI
7C9377D1 C645 FF 00 MOV BYTE PTR SS:[EBP-1],0
7C9377D5 E8 C2FFFFFF CALL ntdll.RtlCallVectoredExceptionHandl>
7C9377DA 84C0 TEST AL,AL
7C9377DC 0F85 84720100 JNZ ntdll.7C94EA66
7C9377E2 53 PUSH EBX
7C9377E3 8D45 F4 LEA EAX,DWORD PTR SS:[EBP-C]
7C9377E6 50 PUSH EAX
7C9377E7 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
7C9377EA 50 PUSH EAX
7C9377EB E8 1CC1FCFF CALL ntdll.RtlpGetStackLimits
7C9377F0 E8 38C1FCFF CALL ntdll.RtlpGetRegistrationHead
7C9377F5 8365 08 00 AND DWORD PTR SS:[EBP+8],0
7C9377F9 8BD8 MOV EBX,EAX
7C9377FB 83FB FF CMP EBX,-1
7C9377FE 0F84 8F000000 JE ntdll.7C937893

Nice, these symbols makes debugging 10x easier

homersux
June 24th, 2005, 16:41
Ok after a couple more days of playing with my target, I think I am getting close to its OEP. After tracing through the last exception:

009FFAA5 C700 EFCA5C85 MOV DWORD PTR DS:[EAX],855CCAEF
009FFAAB 67:64:8F06 0000 POP DWORD PTR FS:[0] <--back here after exception
009FFAB1 83C4 04 ADD ESP,4
009FFAB4 83E8 AF SUB EAX,-51
009FFAB7 83C8 4B OR EAX,4B
009FFABA 58 POP EAX

0012FF34 0012FF80 Pointer to next SEH record
0012FF38 009FFA6E SE handler
0012FF3C E850D8BF

009FFA6E 56 PUSH ESI
009FFA6F F2: PREFIX REPNE: ; Superfluous prefix
009FFA70 EB 01 JMP SHORT 009FFA73
009FFA72 F0:037424 38 LOCK ADD ESI,DWORD PTR SS:[ESP+38] ; LOCK prefix is not allowed
009FFA77 C1DE 83 RCR ESI,83 ; Shift constant out of range 1..31
009FFA7A 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10] <---- retrieve context
009FFA7E 8D76 52 LEA ESI,DWORD PTR DS:[ESI+52] <--- 52+66 = b8
009FFA81 8346 66 06 ADD DWORD PTR DS:[ESI+66],6 <---------- eip+=6
009FFA85 8D7475 6F LEA ESI,DWORD PTR SS:[EBP+ESI*2+6F]
009FFA89 83EE 6F SUB ESI,6F
009FFA8C 5E POP ESI
009FFA8D 83C8 FF OR EAX,FFFFFFFF
009FFA90 40 INC EAX
009FFA91 C3 RETN

I used 'tc eip < 900000' to trace into the 0x401000 code area, I landed here:

0042DB88 E8 DB E8 <---- 0042DB88: E873247A00 CALL 00BD0000
0042DB89 . 73 24 7A 00 ASCII "s$z",0
0042DB8D B1 DB B1
0042DB8E $ E8 6D247A00 CALL 00BD0000
0042DB93 . 7B FF JPO SHORT xxxxxxx.0042DB94 ; JMP to kernel32.ExitProcess


00401000 > $-E9 C8F27A00 JMP 00BB02CD
00401005 84 DB 84
00401006 F0 DB F0
00401007 69 DB 69 ; CHAR 'i'
00401008 1E DB 1E
00401009 3E DB 3E ; CHAR '>'
0040100A BD DB BD
0040100B E0 DB E0
0040100C 8B DB 8B
0040100D 02 DB 02
0040100E 57 DB 57 ; CHAR 'W'
0040100F 2D DB 2D ; CHAR '-'

Ok obviously, this is a asprotect dip in, at this point the target's IAT is available. I can see valid code in this area
004010FE 26 DB 26 ; CHAR '&'
004010FF 2B DB 2B ; CHAR '+'
00401100 . 97 XCHG EAX,EDI
00401101 . 0C 02 OR AL,2
00401103 . 4D DEC EBP
00401104 . 92 XCHG EAX,EDX
00401105 . 6B51 F3 B6 IMUL EDX,DWORD PTR DS:[ECX-D],-4A
00401109 . 62B9 28DF7382 BOUND EDI,QWORD PTR DS:[ECX+8273DF28]
0040110F > E8 6C520400 CALL xxxxxxx.00446380
00401114 . 50 PUSH EAX
00401115 . BB 1E000000 MOV EBX,1E
0040111A . 3B1C24 CMP EBX,DWORD PTR SS:[ESP]
0040111D . 75 25 JNZ SHORT xxxxxxx.00401144
0040111F . 68 40000000 PUSH 40
00401124 . 68 0C304500 PUSH xxxxxo.0045300C ; ASCII "xxxxxxx information"
00401129 . 68 23304500 PUSH xxxxxx.00453023 ; ASCII "Sorry, Windows 98 is not supported!"
0040112E . 68 00000000 PUSH 0
00401133 . E8 9ACB0200 CALL xxxxxx.0042DCD2
00401138 . 68 00000000 PUSH 0 ; /ExitCode = 0
0040113D . E8 52CA0200 CALL xxxxxx.0042DB94 ; \ExitProcess

I am out of idea how I should proceed at this point? It looks like asprotect stole hundreds of bytes from the target...
I traced all the way to the code after the trial timeout messagebox, but it's unclear to me what OEP should look like and is OEP before the trial nag screen or not.