Log in

View Full Version : Packed sdbot variant


stsam
July 21st, 2007, 01:29
this following file is sdbot variant and it's custome packed file.i was able to step till virtualalloc where it writes data from 004900000. but this thing keep's looping here never returns or i am missing something here .

here i have attached the file password:vx

MALWARE/BIOHAZARD

stsam
July 21st, 2007, 04:06
now i can find that it writes some data to 004600000, but still working

stsam
July 21st, 2007, 14:33
now i am getting invalid address at EIP = aa8e3e8f

tryed to pass exception (Shift+f9) but failed , not able to change the EIP address


any other workaround

LLXX
July 22nd, 2007, 23:30
I've been manually tracing the thing in a hex editor ... here's part 1.
Code:
004848B4: 60 pushad
004848B5: BA3E150000 mov edx,00000153E
004848BA: C1E202 shl edx,002 ; edx --> 000054F8
004848BD: 8AC2 mov al,dl ; al --> F8
004848BF: E80C000000 call .0004848D0
004848C4: 6651 push cx
004848C6: EB06 jmps .0004848CE --------
004848C8: 95 xchg ebp,eax
004848C9: AE scasb
004848CA: 21AE1257665B and [esi][05B665712],ebp

004848D0: 5B pop ebx ; ebx --> 004848C4
004848D1: 8BCB mov ecx,ebx ; ecx --> 004848C4
004848D3: 83C10C add ecx,00C ; ecx --> 004848D0
004848D6: 51 push ecx
004848D7: 5B pop ebx ; ebx --> 004848D0
004848D8: 8D5BAC lea ebx,[ebx][-0054] ; 0048487C
004848DB: 8BCA mov ecx,edx ; ecx --> 000054F8
004848DD: 8B4B34 mov ecx,[ebx][00034] ; ecx --> [004848B0] == 000009FA
004848E0: 6653 push bx ; bx --> 48D0
004848E2: 66BB3C67 mov bx,0673C ; useless
004848E6: 66F7C3CF01 test bx,001CF ; useless
004848EB: 665B pop bx ; bx --> 48D0
004848ED: E853000000 call .000484945 ; eax --> 00484952
[ useless instructions here ]
00484901: 8BF0 mov esi,eax ; esi --> 00484952
00484903: EB04 jmps .000484909
[ useless instructions here ]
00484909: 8BFE mov edi,esi ; edi --> 00484952
[ useless instructions here ]
00484914: E800000000 call .000484919
00484919: B8BD000154 mov eax,0540100BD ; eax --> 540100BD
0048491E: 5A pop edx ; edx --> 00484919
0048491F: 42 inc edx ; edx --> 0048491A
00484920: 53 push ebx ; stack: 0048487C
00484921: 33DB xor ebx,ebx ; ebx --> 00000000
00484923: EB05 jmps .00048492A
[ useless instructions here ]

; start of decryption loop
0048492A: AC lodsb ; get byte from [esi]
0048492B: 53 push ebx ; save byte counter
0048492C: 03DA add ebx,edx
0048492E: 3203 xor al,[ebx] ; 0048491A ... 0048491D i.e. BD, 00, 01, 54
00484930: 5B pop ebx ; restore byte counter
00484931: 43 inc ebx ; increment
00484932: EB04 jmps .000484938
[ useless instructions here ]
00484938: 83E303 and ebx,003 ; keep 0...3
0048493B: AA stosb
0048493C: 49 dec ecx ; decrypt 000009FA bytes
0048493D: 75EB jne .00048492A ; could've been replaced with LOOP instr...
0048493F: 61 popad ; remember instruction at 00484920?
00484940: E80D000000 call .000484952
00484945: E800000000 call .00048494A ; stack: 004848F2 0048494A
0048494A: 58 pop eax ; eax --> 0048494A
0048494B: 83C005 add eax,005
0048494E: 83C003 add eax,003 ; eax --> 00484952
00484951: C3 retn
00484952:
[ start of encrypted instructions ]
In essence, a loop is constructed whereby the remainder of the file starting at VA 00484952 and of length 09FA is decrypted via XOR with the constant 0x540100BD.

Kayaker
July 23rd, 2007, 04:07
There's a funny little bit later on I'm not quite sure what to make of.
If you set a breakpoint on VirtualFree (of the earlier VirtualAlloc) you get past the decryption routine LLXX mentions.
Then it goes through the common practice of resolving API addressess with LoadLibrary/GetProcAddress, nothing too exciting so far..

Next it runs a few decryption loops using the stack, lots of pushes and pops. These are fairly easy to trace through without paying much attention to what they're doing, very little SMC and you can always find the "exit" conditional jump out of the decryption loop.

At about the 2nd loop of this kind is resolved another routine which decrypts addresses beginning at 458167.
Nothing unusual about it except that the "exit point" includes a VERR instruction which can't be traced over:

Code:

:0045A91F 60 PUSHAD
:0045A920 03D6 ADD EDX,ESI
:0045A922 8BFE MOV EDI,ESI
:0045A924 61 POPAD
:0045A925 3BF3 CMP ESI,EBX
// EBX = start of decrypt block at 458167
// decryption runs from end->start of block
:0045A927 60 PUSHAD
:0045A928 61 POPAD

:0045A929 0F850A000000 JNZ 0045A939
// have we reached the end of the decrypt block?

// yes, finished decrypting
:0045A92F 0F00E6 VERR SI
:0045A932 E97E000000 JMP 0045A9B5

// no, keep decrypting
:0045A939 6800000000 PUSH 00000000
...
:0045A995 8F06 POP DWORD PTR [ESI]
:0045A997 E983FFFFFF JMP 0045A91F



So when the decryption routine finishes you must execute the instruction
:0045A92F 0F00E6 VERR SI

In Softice at least if you trace over the VERR instruction it causes an exception
If you set a breakpoint on the JMP instruction after VERR and let Softice run, it causes an exception.
If you nop out the VERR instruction it appears you can merrily continue tracing the app.

According to the Intel docs, VERR (Verify a Segment for Reading)
Verifies whether the code or data segment specified with the source operand is readable (VERR) from the current privilege level (CPL). The source operand is a 16-bit register or a memory location that contains the segment selector for the segment to be verified. If the segment is accessible and readable (VERR), the ZF flag is set.

Protected Mode Exceptions
The only exceptions generated for these instructions are those related to illegal addressing of the source operand.



At the point the instruction is executed, ESI contains the starting address of the decryption block, 458167, so SI = 0x8167. From all indications, this WILL cause an exception because the source operand is invalid for the instruction.

As far as I can tell there isn't any debugger detection code that has occurred yet and in all other respects this particular decryption loop looks much like the previous ones, so I'm not sure how or why this VERR instruction pops up and how it's even executable without an exception occurring.

It's very reproducable and after a few test runs you can reach the code quite quickly. I haven't tried tracing in a ring 3 debugger but I just wanted to mention this funny VERR instruction to see if others get the same results.

Kayaker

stsam
July 23rd, 2007, 04:10
thanx waiting for your part 2 , i have moved to virutal alloc section in the decrypted code.

thanx Kayaker , i will try the same.

LLXX
July 23rd, 2007, 05:36
This thing is like an onion, isn't it... 458000 is where the decompressor begins writing to, a two-part operation involving VA'ing a block of memory ~800K, decompressing a block of data to, then writing back to 458000 with another decompression routine, and then VF'ing the now-useless block.

Any thoughts on the process used to create this packer? The part near the beginning with the clearly obfuscated code is probably hand-written, as do appear these loops here, but the decompressor code looks compiler-generated (it occupies 00484AC7 to the end of the file) with the exception of this little useless obfuscatory function at the end, called frequently throughout the decompression code:
Code:
00485341: 9C pushfd
00485342: 6650 push ax
00485344: 66C1E003 shl ax,003
00485348: 6658 pop ax
0048534A: 9D popfd
0048534B: C3 retn
Besides the above, though, the decompressor is one long block of dense compiler-generated bit-manipulating code which I won't bother to reproduce here.

...anyway, here's part 2. Another 0x540100BD XOR with the actual compressed body, VirtualAlloc, decompress, VirtualFree, and imports loader loop.
Code:
00484952: 58 pop eax ; remaining register from popping
00484953: 60 pushad
00484954: BB31684000 mov ebx,000406831 ; ebx --> 00406831
00484959: EB03 jmps .00048495E
[ useless instructions here ]
0048495E: E80C000000 call .00048496F
[ useless instructions here ]
0048496F: 59 pop ecx ; ecx --> 00484963
00484970: 83C10C add ecx,00C ; ecx --> 0048496F
00484973: 8BD9 mov ebx,ecx ; ebx --> 0048496F
00484975: 8D9B0DFFFFFF lea ebx,[ebx][0FFFFFF0D] ; ebx --> 0048487C
0048497B: 011B add [ebx],ebx ; [0048487C] = FFF7B784 + 0048487C = 00400000
0048497D: 8B13 mov edx,[ebx] ; edx --> 00400000
0048497F: 8D7314 lea esi,[ebx][00014] ; esi --> 00484890
00484982: 6A08 push 008
00484984: 59 pop ecx ; ecx --> 00000008

00484985: 0116 add [esi],edx ; add 00400000 to 8 dords starting at 00484890
00484987: AD lodsd
00484988: 49 dec ecx
00484989: 75FA jne .000484985
===> after operation
===> [00484890] = 00484AC7, 0046F148, 00400000, 00458094
===> [004848A0] = 00400000, 00400000, 00000000, 0046F000

0048498B: 8BE8 mov ebp,eax ; ebp --> 0046F000
0048498D: 83C604 add esi,004 ; esi --> 004848B4
00484990: C606E9 mov b,[esi],0E9 ; --> [004848B4] = 0E9
00484993: 8B430C mov eax,[ebx][0000C] --> eax --> [00484888] = FFFD6556
00484996: 894601 mov [esi][00001],eax --> [004848B5] = FFFD6556
00484999: 8B7318 mov esi,[ebx][00018] ; esi --> [00484894] = 0046F148
0048499C: EB26 jmps .0004849C4

decrypt_loop_2:
0048499E: AD lodsd ; (second dord is length to decrypt) eax --> 00015728
0048499F: 8BFE mov edi,esi ; edi --> 0046F150
004849A1: 8BC8 mov ecx,eax ; ecx --> 00015728
004849A3: 33D2 xor edx,edx
004849A5: E800000000 call .0004849AA
004849AA: B8BD000154 mov eax,0540100BD ; this again.
004849AF: 5A pop edx
004849B0: 42 inc edx
004849B1: 53 push ebx
004849B2: 33DB xor ebx,ebx

004849B4: AC lodsb
004849B5: 53 push ebx
004849B6: 03DA add ebx,edx
004849B8: 3203 xor al,[ebx]
004849BA: 5B pop ebx
004849BB: 43 inc ebx
004849BC: 83E303 and ebx,003
004849BF: AA stosb
004849C0: 49 dec ecx
004849C1: 75F1 jne .0004849B4
004849C3: 5B pop ebx
loop_start:
004849C4: AD lodsd
004849C5: 85C0 test eax,eax ; done?
004849C7: 75D5 jne .00048499E

004849C9: 6A04 push 004 ; PAGE_READWRITE
004849CB: 6800100000 push 000001000 ; MEM_COMMIT
004849D0: FF7308 push d,[ebx][00008] ; [00484884] = 000C1CD8 -- 793816 bytes
004849D3: 51 push ecx ; let system determine address
004849D4: FF5524 call d,[ebp][00024] ; [0046F024] = VirtualAlloc
004849D7: 8BD0 mov edx,eax ; edx --> address
004849D9: 8B7318 mov esi,[ebx][00018] ; esi --> [00484894] = 0046F148
004849DC: E99C000000 jmp .000484A7D
decompress_loop_3:
004849E1: 8BF8 mov edi,eax ; 00058000
004849E3: 033B add edi,[ebx] ; edi --> 00058000 + 00400000 = 00458000
004849E5: AD lodsd ; length = 00015728
004849E6: 8BC8 mov ecx,eax ; ecx --> 00015728
004849E8: 0FBAF71F btr edi,01F ; highest bit?
004849EC: 7307 jnc .0004849F5
004849EE: F3A5 repe movsd
004849F0: E988000000 jmp .000484A7D
004849F5: 60 pushad
004849F6: 52 push edx
004849F7: 56 push esi
004849F8: 57 push edi
004849F9: FF5314 call d,[ebx][00014] ; ebx --> 00484AC7 (decompression routine?)
004849FC: 8944241C mov [esp][0001C],eax ; ESP (new stack?)
00484A00: 61 popad
00484A01: 60 pushad
; follows is another block of decompression code...
00484A02: 8BEF mov ebp,edi ; ebp --> 00458000
00484A04: 2B3B sub edi,[ebx] ; edi --> 00058000
00484A06: 8BDF mov ebx,edi ; ebx --> 00058000
00484A08: 8D78FB lea edi,[eax][-0005] ; edi --> 00015723
00484A0B: 33F6 xor esi,esi ; esi --> 00000000
00484A0D: 6AFC push 0FC
00484A0F: 5A pop edx ; edx --> 000000FC
00484A10: EB64 jmps .000484A76
00484A12: 8A042E mov al,[esi][ebp] ; get a byte
00484A15: 24FE and al,0FE ; 11111110
00484A17: 3CE8 cmp al,0E8 ; 11101000
00484A19: 740D je .000484A28
00484A1B: 8B042E mov eax,[esi][ebp]
00484A1E: 80E4F0 and ah,-010
00484A21: 663D0F80 cmp ax,0800F
00484A25: 754E jne .000484A75
00484A27: 46 inc esi
00484A28: 8BC6 mov eax,esi
00484A2A: 2BC2 sub eax,edx
00484A2C: 3403 xor al,003
00484A2E: 8BD6 mov edx,esi
00484A30: 8A4C2E04 mov cl,[esi][ebp][00004]
00484A34: 41 inc ecx
00484A35: D0E9 shr cl,1
00484A37: 753C jne .000484A75
00484A39: 57 push edi
00484A3A: 46 inc esi
00484A3B: 8B3C2E mov edi,[esi][ebp]
00484A3E: 2BFB sub edi,ebx
00484A40: 2BFE sub edi,esi
00484A42: 893C2E mov [esi][ebp],edi
00484A45: 83F803 cmp eax,003
00484A48: 771A ja .000484A64
00484A4A: 8BC8 mov ecx,eax
00484A4C: C1E103 shl ecx,003
00484A4F: BFFF000000 mov edi,0000000FF ; 255
00484A54: D3E7 shl edi,cl
00484A56: 333C2E xor edi,[esi][ebp]
00484A59: 8D0C30 lea ecx,[eax][esi]
00484A5C: 8A0C29 mov cl,[ecx][ebp]
00484A5F: 41 inc ecx
00484A60: D0E9 shr cl,1
00484A62: 74DA je .000484A3E
00484A64: 83C603 add esi,003
00484A67: 8A0C2E mov cl,[esi][ebp]
00484A6A: D0E9 shr cl,1
00484A6C: 0F93C5 setae ch
00484A6F: FECD dec ch
00484A71: 882C2E mov [esi][ebp],ch
00484A74: 5F pop edi
00484A75: 46 inc esi ; esi = loop counter
00484A76: 3BF7 cmp esi,edi
00484A78: 7C98 jl .000484A12
00484A7A: 61 popad
00484A7B: 03F1 add esi,ecx
start_loop3:
00484A7D: AD lodsd
00484A7E: 85C0 test eax,eax
00484A80: 0F855BFFFFFF jne .0004849E1

00484A86: 6800800000 push 000008000 ; MEM_DECOMMIT
00484A8B: 50 push eax ; size = 0
00484A8C: 52 push edx ; address
00484A8D: FF5520 call d,[ebp][00020] ; [0046F020] = VirtualFree
00484A90: 8B7320 mov esi,[ebx][00020] ; esi --> [0048489C] = 00458094
00484A93: EB27 jmps .000484ABC
import_module_loop:
00484A95: 0303 add eax,[ebx] ; add 00400000
00484A97: 50 push eax
00484A98: FF550C call d,[ebp][0000C] ; [0046F00C] = GetModuleHandleA
00484A9B: 8B3E mov edi,[esi] ; next dord points to imports
00484A9D: 033B add edi,[ebx] ; add imagebase = 00400000
00484A9F: EB12 jmps .000484AB3
load_imports_loop:
00484AA1: 0FBAF11F btr ecx,01F
00484AA5: 7204 jc .000484AAB ; import by ordinal?
00484AA7: 030B add ecx,[ebx]
00484AA9: 41 inc ecx ; original import table contains word before name
00484AAA: 41 inc ecx
00484AAB: 50 push eax ; save hModule
00484AAC: 51 push ecx ; lpProcName
00484AAD: 50 push eax ; hModule
00484AAE: FF5508 call d,[ebp][00008] ; [0046F008] = GetProcAddress
00484AB1: AB stosd ; store address
00484AB2: 58 pop eax ; recover hModule

00484AB3: 8B0F mov ecx,[edi] ; get an import
00484AB5: 85C9 test ecx,ecx
00484AB7: 75E8 jne .000484AA1 ; more imports to load?
00484AB9: 83C610 add esi,010 ; padding?

00484ABC: AD lodsd
00484ABD: 85C0 test eax,eax
00484ABF: 75D4 jne .000484A95 ; load imports
00484AC1: 61 popad
00484AC2: E9EDFDFFFF jmp .0004848B4 ;
(I know, many would rather rip the wrapping apart to get to the gift in the box, but I prefer slow and steady, trying to understand as much of the code as possible )

stsam
July 23rd, 2007, 07:18
as u said there is execption occured at ":0045A92F 0F00E6 VERR SI"

i have nop 'ed that instruction and moving on to decrypt this file

stsam
July 23rd, 2007, 07:24
after this instruction there is a exception

Code:
00459483 64:FF33 PUSH DWORD PTR FS:[EBX]
00459486 64:8923 MOV DWORD PTR FS:[EBX],ESP
00459489 FE03 INC BYTE PTR DS:[EBX]


access violation when executing[FCa80012]


tried passing exception with shift+f9 ( twice)

finally process terminated with exit code c0000005[-1073741819]

yes this packer is really onion and i would wait as u reveal how it unpacks thanx a lot LLXX

blabberer
July 23rd, 2007, 12:39
is this vm aware ?

i mean did any of encounter sidt instruction in vm

Code:

0045ADCC . 0F010B SIDT FWORD PTR DS:[EBX]



for referance

http://mark.michaelis.net/Blog/PermaLink.aspx?guid=4c9438b7-c818-457d-9b5b-c46bed8b494b

http://mark.michaelis.net/Blog/WowCIsAmazing.aspx

Kayaker
July 23rd, 2007, 12:57
Quote:
[Originally Posted by blabberer;67311]is this vm aware ?

i mean did any of encounter sidt instruction in vm

Code:

0045ADCC . 0F010B SIDT FWORD PTR DS:[EBX]






Nice spot blabberer, yep I traced over that and marked it for future study, but didn't make the Redpill connection.

Ah hell, ... caught in the Matrix

blabberer
July 23rd, 2007, 13:26
ok look like i have to drop this now

it allocates three virtual allocs
there are three exceptions one is already posted
the other is an idiv

and when it is all done
it executes some blah blah in virtual alloced space which finally writes to 0x401000 place

the strings at this postion are like this in the attachment below

i had to abandon due to lack of time atm
but looks like if traced carefully one should be able to bypass all and get to the oep

ZaiRoN
July 23rd, 2007, 15:13
Quote:
but looks like if traced carefully one should be able to bypass all and get to the oep
Is it really necessary to trace the packer? I did unpack the malware using one breakpoint and looking at the graph view provided by IDA. I mean, bpx VirtualAlloc (one of the few function to bpx in these cases...), go back to the malware code and look at the diagram. Nothing more.

The image below shows the graph after the execution of the third VirtualAlloc. The current eip value is inside the dotted rectangle. As you can see there are a lot of cycles but the most important thing is that there is only one possible exit (not really true because there is another one but it's at the beginning of the diagram, but you can forget it). The exit block contains:
Code:
004584D3 POPAD
004584D4 POPFD
004584D5 JMP 0041080E
Well, a popad followed by a popfd followed by a jmp into the first section. Maybe I'm on the right way

Quote:
is this vm aware ?
I don't think but I didn't inspect too much.

Just my 2 cents...

stsam
July 24th, 2007, 01:29
we have all reached OEP safely

here is how i went , loaded the file into ollydbg

pressed shift+f9
Code:
0045A92F 0F00E6 VERR SI


NOP'ed it then press shift+f9
Code:
00459489 FE03 INC BYTE PTR DS:[EBX]


EBX=0 ; Access violation

press sift+f9

Code:
0045824B F7F2 DIV EDX

EDX=0 ; Integer division by zero

kept BP at
Code:
004582D4 FF95 8CFEFFFF CALL DWORD PTR SS:[EBP-174]



then pressed shift+f9 then alt+f9

kept BP at
Code:
004584D5 ^E9 3483FBFF JMP wintvjyw.0041080E


press F9

here i am OEP
Code:
0041080E E8 55850000 CALL wintvjyw.00418D68



dump and fixed with ImportREC

MALWARE/BIOHAZARD

LLXX
August 22nd, 2007, 17:31
Aging this thread for a small addendum:

This packer appears to be based on ASProtect/ASPack. In particular, VirtualAlloc/VirtualFree sequences and import loader loop are very reminiscent of such.