Log in

View Full Version : Cyberheg SuperPro Shell Tuts help please


sope
December 12th, 2002, 15:41
Hi, to all

I am working on a target & i don't have the dongle.
Reading Cyberheg tuts on Breaking the shell i have marked the similar
type of code which i come across in the tut.

I found the main switch & below the result
First time we have
msg (1) CD03

00FB1DE5 callby_CD03: ; CODE XREF: start+20Aj
00FB1DE5 mov ax, :word_FA7C4C-->ax=03D5
00FB1DEB mov ecx, :dword_FA7C40--ecx=FA6CA8
00FB1DF1 push eax
00FB1DF2 push ecx
00FB1DF3 call sub_FB16C0 ; depending on ax we have value in eax
00FB1DF8 add ff_FA7C38, edi; this subtracts 4 (add 0xFA7C38, 0xFFFFFFFC = 0xFA7C34)
00FB1DFE mov ecx, ff_FA7C38 ecx=FA7C34
00FB1E04 add esp, 8
00FB1E07 mov :dword_FA7C40, eax -->eax=FA6CA8
00FB1E0C mov [ecx], eax -->save it
00FB1E0E jmp continuedelay


msg (2) BA51 ---> Calls SproFindNextUnit &
Calls sproFormatPacket & fills 0x404 bytes (1028 bytes) with defaults i guess.

msg (3) 22B7

00FB1B2A call sub_FB16C0 ; get our response
00FB1B2F add esp, 8
00FB1B32 mov ecx, ff_FA7C38 ; get constant ecx=0xFA7C34
00FB1B38 sub [ecx], eax ; subtract eax=0
00FB1B3A jmp continuedelay ; continue

msg (4) 0611

00FB1A14
00FB1A14 loc_FB1A14: ; CODE XREF: start+28Aj
00FB1A14 ; start+297j
00FB1A14 mov eax, ff_FA7C38
00FB1A19 add ff_FA7C38, esi
00FB1A1F cmp dword ptr [eax], 0
00FB1A22 jz continuedelay ; was the result zero?
00FB1A28 mov eax, :dword_FA7C40
00FB1A2D mov ff_FA7C3C, eax
00FB1A32 jmp continuedelay

Default the result will be zero and the jump will occur. So far so good.

msg (5) 1A44 ---- GetQuery

00FB1AE0 callby_1A44: ; CODE XREF: start+107j
00FB1AE0 add ff_FA7C38, edi (subtracts 4 --> FA7C38-4 = FA7C34)
00FB1AE6 call :dword_FA7C40 ; Call GetQuery
00FB1AEC mov ecx, ff_FA7C38 ; get where to save
00FB1AF2 mov [ecx], eax ; save -->eax=0
00FB1AF4 jmp continuedelay ; continue

msg (6) CD03 (2nd Time) CD03 look up after the Call subtracts 4 from FA7C34 which become FA7C30
mov [ecx], eax -->stores eax = 0xFA5004 in ecx = 0xFA7C30

msg (7) CD03 (3rd Time) CD03 look up after the Call subtracts 4 from FA7C30 which become FA7C2C
mov [ecx], eax -->stores eax = 0xFA5290 in ecx = 0xFA7C2C

msg (8) 22B7 (2nd time)

00FB1B1C callby_22B7: ; CODE XREF: start+124j
00FB1B1C mov ax, :word_FA7C4C ax=0x03D5
00FB1B22 mov ecx, :dword_FA7C40 ECX=0xFA5004
00FB1B28 push eax
00FB1B29 push ecx
00FB1B2A call sub_FB16C0 ; get our response
00FB1B2F add esp, 8 EAX = FA5004
00FB1B32 mov ecx, ff_FA7C38 ; get constant ECX=FA7C2c
00FB1B38 sub [ecx], eax ; subtract in my case FA5290-FA5004=00008C02 = 028C0000
00FB1B3A jmp continuedelay ; continue

Doubt: I want to clarify is 0000028C is the constant for this target ? This is also used in msg B323 Decrypting
routine see below B323

continue.... next post pls...
attached a file ask.zip

sope
December 12th, 2002, 15:44
continue from above post ....


msg (9) CD03 (4th Time) below is the code & value

00FB1DE5 callby_CD03: ; CODE XREF: start+20Aj
00FB1DE5 mov ax, :word_FA7C4C-->ax=0234
00FB1DEB mov ecx, :dword_FA7C40--ecx=FA5000 VA of Section 7
00FB1DF1 push eax
00FB1DF2 push ecx
00FB1DF3 call sub_FB16C0 ;
00FB1DF8 add ff_FA7C38, edi; EAX=0x16E8B35
the addition actuall subtracts 4 (0xFA7C2C-4 = 0xFA7C28)
00FB1DFE mov ecx, ff_FA7C38 ecx=FA7C28 where to save
00FB1E04 add esp, 8
00FB1E07 mov :dword_FA7C40, eax
00FB1E0C mov [ecx], eax -->save eax=16E8B35
00FB1E0E jmp continuedelay


msg (10) B323 ---> call the Decrypting Routine

00FB1D7B callby_B323: ; CODE XREF: start+1EFj
00FB1D7B mov ebp, ff_FA7C38
00FB1D81 mov eax, ff_FA7C38 ; response address
00FB1D86 add ebp, 8
00FB1D89 mov ecx, [eax] ; our response = 16E8B35
00FB1D8B push ecx ecx=16E8B35
00FB1D8C mov edx, [eax+4]
00FB1D8F push edx edx=028C = doubt: counter or constant ?
00FB1D90 mov ecx, [ebp+0]
00FB1D93 push ecx ecx = FA5004
00FB1D94 call :dword_FA7C40 ; my case call 0xFB1EF0
00FB1D9A mov [ebp+0], eax
00FB1D9D add ff_FA7C38, ebx
00FB1DA3 jmp continuedelay


Call 0xFB1EF0

00FB1EF0 loc_FB1EF0: ; DATA XREF: 0000:00FA7394o
00FB1EF0 ; 0000:00FA7B54o
00FB1EF0 push ebx
00FB1EF1 xor eax, eax
00FB1EF3 push esi
00FB1EF4 push edi
00FB1EF5 mov esi, [esp+14h] ; counter esi=028C
00FB1EF9 shr esi, 2 esi=A3
00FB1EFC mov ecx, esi ecx=A3
00FB1EFE dec esi esi=A2
00FB1EFF test ecx, ecx zero ?
00FB1F01 jz short loc_FB1F34 ; Finish
00FB1F03 mov edx, [esp+10h] ; decryption_start_address = FA5004
00FB1F07 mov edi, [esp+18h] ; our response = 16E8B35


00FB1F0B loc_FB1F0B: ; CODE XREF: start+7C2j
00FB1F0B mov ecx, edi -->ecx=16E8B35
00FB1F0D mov ebx, edi -->edx=16E8B35
00FB1F0F shl ecx, 4 -->ecx=16E8B350
00FB1F12 add edx, 4 -->edx=FA5008 is this next DWORD ?
00FB1F15 shl ebx, 5 -->ebx=2DD166A0
00FB1F18 add ecx, edi -->ecx=18573E85 -->(16E8B350 = [i.e. ecx after shl 4] + 16E8B35 [our response])
00FB1F1A shr ecx, 9 -->ecx=C2B9F
00FB1F1D xor ecx, ebx -->ecx= 2DDD4D3F (C2B9F ^ 2DD166A0 [i.e. our response 16E8B35 shl 5] )
00FB1F1F add edi, ecx -->EDI=2F4BD874 ---> (our response 16E8B35 + 2DDD4D3F)
00FB1F21 mov ecx, [edx-4] --> [edx-4] = [FA5004] = 2F55D874 original bytes
00FB1F24 xor ecx, edi --> ECX=1E0000
00FB1F26 add eax, ecx --> EAX=0+1E0000 = 1E0000
00FB1F28 mov [edx-4], ecx -->save it in [FA5004] = 00001E00 new bytes
00FB1F2B xor edi, eax --> EDI=2F55D874 (2F4BD874 ^ 1E0000)
00FB1F2D mov ecx, esi --> ECX=A2
00FB1F2F dec esi --> ESI=A1
00FB1F30 test ecx, ecx --> is it zero ?
00FB1F32 jnz short loc_FB1F0B loop
00FB1F34
00FB1F34 loc_FB1F34: ; CODE XREF: start+791j
00FB1F34 pop edi
00FB1F35 pop esi
00FB1F36 pop ebx
00FB1F37 retn 0Ch


I am know understanding what u mean to say in below para.

/Tuts - As per tut first we get tResponse from tResponse += (((tResponse << 4) + tResponse) >> 9) ^ (tResponse << 5)
tResponse = 2F4BD874

This gets xor'ed with the first DWORD to decrypt which is stored in *(lpCryptedBuffer).

00FB1F21 mov ecx, [edx-4] --> [edx-4] = [FA5004] = 2F55D874 original bytes
00FB1F24 xor ecx, edi --> ECX=1E0000 <<--- here it gets xored & we get decrypted DWORD

In *(lpUnCryptedBuffer) = FA5004 we have the first decrypted DWORD 0x001E0000 which in this example is wrong. Becuase Sum = EAX starts with 0, sum will become the same value as the decrypted DWORD.
00FB1F26 add eax, ecx --> sum = EAX = 0 + decrypted DWORD 1E0000 = 1E0000

Next when xor'ed with tResponse, tResponse will hold
the first encrypted DWORD from the file 0xF4120473. -Tuts/

00FB1F2B xor edi, eax --> original encrypted DWORD = EDI=2F55D874 (2F4BD874 ^ 1E0000)


Best Regards
Sope

cyberheg
December 12th, 2002, 20:30
Heh!

Looking back I am not sure I even understand my own explanation.
What I did mean however is that there several bugs in the algorithm used for decryption the sections. I'm sure you do understand that the decryption goes on blockwise in chunks of 32 bits. The 2nd dword will get decrypted correctly no matter which key is used. This means on 2nd round you should be getting some plaintext. Your task is now to start guessing the first 4 bytes of plaintext and code a program to verify your guess.

Another way which is better is to implement a full bruteforcer for this. Some months after writing the article I wrote a distributed system much like the Distributed.net challange which I used to break sentinel shell with. With a little luck any sentinel shell would fall within 10 minutes on maybe 5 computers using a very optimised version of the algorithm. Using a less optimised one it would take like 2 hours to break but then it should also work on almost any program using sentinel shell.

As for the rest if your questions about emulation it's the same which goes on in every program I've seen. It starts with those sproread calls and ends with the sproquery calls.

// CyberHeg

sope
December 13th, 2002, 07:46
Hi CyberHeg

Thank you for your time & reply.

I now do understand what you mean in the above para.
I have modified it accordingly.

> Your task is now to start guessing the first 4 bytes of
> plaintext and code a program to verify your guess.

> Another way which is better is to implement a full bruteforcer

ok! now i get stuck. I need to find examples of bruteforcer
to understand what you are trying to tell.

Just 1 more question suppose if i leave that byte in my case 1E0000
& go ahead with other messages which will follow (a long list)
would it be of use or at some point later in the program original bytes will be required ?

Regards
Sope

CrackZ
December 14th, 2002, 14:59
Hiya,

To add to Cyberheg's essay/post.

The basic challenge of the Sentinel Shell (if one could call it that) is to guess a valid byte or if you are trying to do it really quickly, a dword, of the section you are trying to decrypt. On very small sections (say 0x10000h) or less one can quite simply try all the possible combinations, just rip the decryption routine out that you have pasted above and the data you are decrypting, add a quick loop and check the value in EAX at the end against the sanity check value from your target.

On larger code sections this isn't practicle to do, it might take a few weeks or more on a single PC, like Cybh says, a bit more computing power and away you go.....essentially the only thing you can then do is reduce your keyspace by quickly scrapping unlikely key candidates, so lets say you decrypt the first dword, and examine whether the decrypted data it produces has a likely byte in the first position, I reckon from discussion with Cybh and others, if you check for 68/6A/90/55/00 and one other byte that escapes my memory right now (perhaps they'll post it, might be C3?), you cut the complexity of the brute force, since you only need decrypt the entire data for keys satisfying that criteria.

It doesn't take a genius to work out that with a bit of luck you'll have the key required a lot quicker than a straight search of the keyspace, of course if you examine other files in your target you can probably guess/look for better bytes :P. Any further help you need drop me some files and I'll let you know how I get on ;-).

Regards

CrackZ.

cyberheg
December 15th, 2002, 11:49
Quote:
Originally posted by sope

Just 1 more question suppose if i leave that byte in my case 1E0000
& go ahead with other messages which will follow (a long list)
would it be of use or at some point later in the program original bytes will be required ?


CrackZ gave you some good notes on how to make a bruteforcer so go ahead and makine it now.

I'm not sure I understand your second question. If you don't recover the real bytes of the program it will crash when you reach the program entrypoint.

// CyberHeg

sope
December 16th, 2002, 08:25
Hi CrackZ / CyberHeg

CrackZ:

I need to clarify 1 thing i.e. Sanity check value of my target

> just rip the decryption routine out that
I understand this line.

> the data you are decrypting,
Ok with this too.

> check the value in EAX at the end against the sanity check value
> from your target.

I need to clarify what do you mean by sanity check value of my target

First time EAX = 0x1E0000 after decryption,

do you mean to say first crypted DWORD 0x2F55D874h

or you mean to say i need to find the value (our_response)
which will after performing the above decryption routine
we should have the value 0x2F55D874h in EAX ?

am i thinking right, i am not getting your hint.

CyberHeg:

I was trying to ask is suppose i leave the first Decrypted DWORD i.e.
(0x001E0000) in my case which is wrong & move forward with other messages
which will follow. I tried BPM on the address where the DOWRD i.e.
(1E0000) get stored thinking i might be used somewhere but it was not
used. Hence i asked you a question about it.

I got the reply. I need to find the correct DWORD at first decryption level.

Regards
Sope

sope
December 17th, 2002, 08:42
Hi to all

I need to clarify is this the sanity check value which i get by tracing the returned call 74BB which gets xor'ed with 4D82A4E6 & then followed with a compare call 0611 which
cmp dword ptr [eax],0 ; was the value zero ?
jmp continuedelay ; continue

So i guess 4D82A4E6 is the sanity check value which you are referring.

Please any one who can look at the code & tell me if i did the
brute force in corret way. attached file "brut.zip"

Regards
Sope

sope
December 17th, 2002, 16:14
Hi, to all

I guess, reached OEP & it crashed.
reason: decryption is done with a wrong query response.

I need to find the right query response for the decryption stage all will
go through.

Can anybody confirm is this below pattern for OEP of Sentinel Shell ?

00FB1EA7 C20C00 RET 000C
00FB1EAA 8B44241C MOV EAX,[ESP+1C]
00FB1EAE 8B4C2418 MOV ECX,[ESP+18]
00FB1EB2 8B542414 MOV EDX,[ESP+14]
00FB1EB6 50 PUSH EAX
00FB1EB7 51 PUSH ECX
00FB1EB8 52 PUSH EDX
00FB1EB9 FF15706BFA00 CALL [00FA6B70] ; this will lead to OEP
00FB1EBF 5D POP EBP
00FB1EC0 5F POP EDI

Regards
Sope

cyberheg
December 21st, 2002, 22:11
Quote:
Originally posted by sope
Hi, to all

I guess, reached OEP & it crashed.
reason: decryption is done with a wrong query response.

I need to find the right query response for the decryption stage all will
go through.

Can anybody confirm is this below pattern for OEP of Sentinel Shell ?

00FB1EA7 C20C00 RET 000C
00FB1EAA 8B44241C MOV EAX,[ESP+1C]
00FB1EAE 8B4C2418 MOV ECX,[ESP+18]
00FB1EB2 8B542414 MOV EDX,[ESP+14]
00FB1EB6 50 PUSH EAX
00FB1EB7 51 PUSH ECX
00FB1EB8 52 PUSH EDX
00FB1EB9 FF15706BFA00 CALL [00FA6B70] ; this will lead to OEP
00FB1EBF 5D POP EBP
00FB1EC0 5F POP EDI

Regards
Sope


Yeah I think it's correct. The function which calls the error message is the same one calling OEP.
As you wrote yourself it's most likely that the program crashes because of wrong query responses.

At first sight your bruteforcer looks ok but I didn't compile it or try it since I don't got your target to compare with.

There are some things which makes me think you did something wrong though. Firstly the file 1.bin is very small. The first query response is for the whole code section so having a file so small makes me think you picked the wrong data. The compare to see if the decryption is correct looks fine though. Another thing is the initial query response.

our_response dd 01600000h ; start with this value

What makes you think it's nearby? Guessing?

// CyberHeg

CrackZ
December 22nd, 2002, 02:22
Hiya Sope,

Now that I have your target.....

I won't post the entire set of notes I have for you until I've broken it myself, you'll learn more that way I think.

But to confirm, the first section is decrypted from address 0x401000 and has a size of 0x334EA6 bytes (about 3.2Mb's), this makes bruteforcing the entire keyspace pretty much a non-existant option, I'm trying a reduced keyspace search right now, but I think even my method is looking like 24hrs or so (and of course there is no guarantee I will even find the key ;-) ).

The sanity check value for the first section is 0x58E1CD28, I don't know where you got the other value from ;-).

Regards, I'll post more when I've got the answers .....

CrackZ.

sope
December 22nd, 2002, 08:55
Hi CyberHeg / CrackZ

CyberHeg:

> Yeah I think it's correct. The function which calls the error message is the same one calling OEP.
> At first sight your bruteforcer looks ok
Thanks for the confirmation of both things brute force & OEP.

> There are some things which makes me think you did something wrong though.
> Firstly the file 1.bin is very small. The first query response is for the whole code section
> so having a file so small makes me think you picked the wrong data. The compare to see if the
> decryption is correct looks fine though. Another thing is the initial query response.

> our_response dd 01600000h ; start with this value
> What makes you think it's nearby? Guessing?

I'll try to clarify it. I picked up the the small file because i was not
sure about the brut program i wrote & the sanity check value which CrackZ was referring to.

I saw that the shell first time decrypts 028C bytes with a good response 16E8B35 which is already there inside the exe file & hence i made the brut start with 01600000h.

CrackZ:

> But to confirm, the first section is decrypted from address 0x401000 and has a size of 0x334EA6 bytes (about 3.2Mb's),
> this makes bruteforcing the entire keyspace pretty much a non-existant option, I'm trying a reduced keyspace search
> right now, but I think even my method is looking like 24hrs or so

I did followed your hints/advice & i tried too try to reduce the key space searching for the first byte of decrypted section
for the below value 68/6A/90/55/00/C3 added /CC /C7 / 6D to it but still no luck.

> (and of course there is no guarantee I will even find the key ;-) ).
yeah! i can understand. Now some guessing & luck is all that we want

> The sanity check value for the first section is 0x58E1CD28,

Thanks for the confirmation.

> I don't know where you got the other value from ;-).
Once you reach the 3rd time B323 i.e. the decryption routine for section 401000 size 334EA6 i dumped section 7 why ? because i saw that the sanity value which we get is from that section address space. so i dumped the whole section 7.
& I searched for the byte 28 CD E1 58 shown below

A6 4E 33 00 6E 61 27 B8 28 CD E1 58 00 00 00 00
00 90 34 00 00 10 01 00 E8 ED DA B6 6D C7 7B A9

What we see is the next decryption routines sanity check also there.

3rd time B323 decryption routine: sanity check value 58E1CD28 & size 334EA6

4th time B323 decryption routine : sanity check value A97BC76D & size 0x00011000 [Section 3]

Also i confirmed this by tracing the msg which came & fourth time i reached B323 decrypting routine & then msg 74BB we get the same sanity check value which is already there.

After this i reach the OEP & a Crash.....this is obvious.

Regards
Sope

CrackZ
January 5th, 2003, 16:34
Hiya Sope,

OK, since I now have your target, here is how I proceeded ;-). I hope it helps you.

1. Locate Sentinel functions.

FB8EB0 - sproFindFirstUnit()
FB9080 - sproRead()
FB9470 - sproQuery()

2. Order of events.

1st break - sproFindFirstUnit(Developer ID 0xF580), patch :

00BACED1: 00 0E
00BACED4: 00 02

2nd break - sproRead(Words 0x30,0x34,0x38,0x3C,0x0), patch :

00BAD0A1: 00 0E
00BAD0A2: 55 66
00BAD0A3: 8B B8
00BAD0A4: 44 02
00BAD0A5: 24 00
00BAD0A6: 14 5F
00BAD0A7: D1 5E
00BAD0A8: E0 C2
00BAD0A9: E8 0C
00BAD0AB: 00 05
00BAD0AE: 5D 00
00BAD0AF: 8D 00
00BAD0B0: 7D F6
00BAD0B1: 17 46
00BAD0B2: 0F 12
00BAD0B3: B7 04
00BAD0B4: 04 75
00BAD0B5: 38 0F
00BAD0B6: 8B 66
00BAD0B7: 7C C7
00BAD0B8: 24 46
00BAD0B9: 18 06
00BAD0BA: 66 39
00BAD0BB: 89 0B
00BAD0BC: 07 66
00BAD0BD: 33 B8
00BAD0BE: C0 39
00BAD0BF: 5D 00
00BAD0C5: 39 8B
00BAD0C6: 30 7C
00BAD0C7: 80 24
00BAD0C8: F5 14
00BAD0C9: FF 0B
00BAD0CB: FF 75
00BAD0CC: FF 13
00BAD0CD: FF 66
00BAD0CE: FF C7
00BAD0CF: FF 46
00BAD0D0: FF 06
00BAD0D1: FF 10
00BAD0D2: FF 04
00BAD0D3: FF 66
00BAD0D4: FF B8
00BAD0D5: 08 10
00BAD0D6: 08 00
00BAD0D7: 09 5F
00BAD0D8: 09 5E
00BAD0D9: 0A C2
00BAD0DA: 0A 0C
00BAD0DB: 0B 00
00BAD0DC: 0B 8D
00BAD0DD: 0C 64
00BAD0DE: 0C 24
00BAD0DF: 0D 00
00BAD0E0: 0D 66
00BAD0E1: 0E C7
00BAD0E2: 0E 46
00BAD0E3: 0F 30
00BAD0E4: 0F 0A
00BAD0E5: 10 00
00BAD0E6: 10 66
00BAD0E7: 11 8B
00BAD0E8: 11 44
00BAD0E9: 12 24
00BAD0EA: 12 10
00BAD0EB: 13 66
00BAD0EC: 13 89
00BAD0ED: 14 46
00BAD0EE: 14 34
00BAD0EF: 15 56
00BAD0F0: 15 E8
00BAD0F1: 16 6B
00BAD0F2: 16 E7
00BAD0F3: 17 FF
00BAD0F4: 17 FF
00BAD0F5: 18 0A
00BAD0F6: 18 C0
00BAD0F7: 19 75
00BAD0F8: 19 17
00BAD0F9: 1A 66
00BAD0FA: 1A 8B
00BAD0FB: 1B 46
00BAD0FC: 1B 36
00BAD0FD: 1C 66
00BAD0FE: 1C 89
00BAD0FF: 1D 07
00BAD100: 1D 66
00BAD101: 1E 8B
00BAD102: 1E 46
00BAD103: 1F 06
00BAD104: 1F 50
00BAD105: 20 E8
00BAD106: 20 A6
00BAD107: 21 F5
00BAD108: 21 FF
00BAD109: 22 FF
00BAD10A: 22 5F
00BAD10B: 23 5E
00BAD10C: 23 C2
00BAD10D: 24 0C
00BAD10E: 24 00
00BAD10F: 25 90
00BAD110: 25 66
00BAD111: 26 8B
00BAD112: 26 46
00BAD113: 27 06
00BAD114: 27 50
00BAD115: 28 E8
00BAD116: 28 96
00BAD117: 29 F5
00BAD118: 29 FF
00BAD119: 2A FF
00BAD11A: 2A 66
00BAD11B: 2B 3D
00BAD11C: 2B 0C
00BAD11D: 2C 00
00BAD11E: 2C 75
00BAD11F: 2D E0
00BAD120: 2D 66
00BAD121: 2E B8
00BAD122: 2E 03
00BAD123: 2F 00
00BAD124: 2F 5F
00BAD125: FF 5E
00BAD126: FF C2
00BAD127: 31 0C
00BAD128: 31 00
00BAD129: 32 8D
00BAD12A: 32 A4
00BAD12B: 33 24
00BAD12C: 33 00
00BAD12D: FF 00
00BAD12E: FF 00
00BAD12F: 35 00
00BAD130: 35 53
00BAD131: 36 56
00BAD132: 36 57
00BAD133: 37 8B
00BAD134: 37 44
00BAD135: FF 24
00BAD136: FF 10
00BAD137: 39 0B
00BAD138: 39 C0
00BAD139: 3A 75
00BAD13A: 3A 0A
00BAD13B: 3B 66
00BAD13C: 3B B8
00BAD13D: FF 02
00BAD13E: FF 00
00BAD13F: 3D 5F
00BAD140: 3D 5E
00BAD141: 3E 5B
00BAD142: 3E C2
00BAD143: 3F 10
00BAD144: 3F 00

Full sproRead() emulation, we patch words 0x30/0x34/0x38/0x3C all to 0xFFFFh and the
dongle serial number to 0x3039 (12345) ;-).

3rd break - sproQuery(), identify Cybh's GetQuery(sub_FB1590) & GetResponse(sub_FB15A0).
First break however is algorithm descriptor of 0. Code preliminary emulation routine for this :

00BAD493: 00 0C
00BAD494: A1 66
00BAD495: E4 B8
00BAD496: F8 02
00BAD497: FA 00
00BAD498: 00 5F
00BAD499: 8B 5E
00BAD49A: 7C 5B
00BAD49B: 24 C2
00BAD49D: 3B 00
00BAD49E: 07 8B
00BAD49F: 75 FF
00BAD4A0: 0E F6
00BAD4A1: 8B 46
00BAD4A2: 7C 12
00BAD4A3: 24 04
00BAD4A4: 1C 75
00BAD4A5: 89 10
00BAD4A6: 07 66
00BAD4A7: 33 C7
00BAD4A8: C0 46
00BAD4A9: 5F 06
00BAD4AA: 5E 39
00BAD4AB: 5B 0B
00BAD4AC: C2 66
00BAD4AD: 18 B8
00BAD4AE: 00 39

4th & 5th breaks - sproQuery(), this time we need to handle GetQuery() & GetResponse().

00BAD4AF: E8 00
00BAD4B0: DC 5F
00BAD4B1: 80 5E
00BAD4B2: FF 5B
00BAD4B3: FF C2
00BAD4B4: 35 18
00BAD4B5: D6 00
00BAD4B6: 99 8B
00BAD4B7: 06 44
00BAD4B8: FD 24
00BAD4B9: 8B 18
00BAD4BA: 7C 0B
00BAD4BB: 24 C0
00BAD4BC: 18 75
00BAD4BD: 3B 12
00BAD4BE: 07 66
00BAD4BF: 75 C7
00BAD4C0: 18 46
00BAD4C1: E8 06
00BAD4C2: DA 10
00BAD4C3: 80 04
00BAD4C4: FF 66
00BAD4C5: FF B8
00BAD4C6: 35 10
00BAD4C7: A7 00
00BAD4C8: 09 5F
00BAD4C9: 23 5E
00BAD4CA: 7B 5B
00BAD4CB: 8B C2
00BAD4CC: 7C 18
00BAD4CD: 24 00
00BAD4CE: 1C 8B
00BAD4CF: 89 FF
00BAD4D0: 07 66
00BAD4D1: 33 8B
00BAD4D2: C0 5C
00BAD4D3: 5F 24
00BAD4D4: 5E 24
00BAD4D5: 5B 66
00BAD4D6: C2 83
00BAD4D7: 18 FB
00BAD4D8: 00 38

6th break - sproQuery(static query data 0xB827616E). This does the first round of decryption.
Start address 401000, size 0x334EA6 bytes, correct result should be 0x58E1CD28. The decryption
routine is FB1EF0. Recovering the key ..... My brute force code enclosed, the size of the
section is 3.2Mb's so essentially you are going to have to get lucky ;-).

Addendum - You did get it in the end by brute force, response is 0xD53B03F3, general point here really was that you got just 1 .exe so guessing any sort of plaintext was never going to be easy, a lucky guess on the first byte though of 0xCC would have reduced the time to a few hours ;P.

7th break - sproQuery(static query data 0xB6DAEDE8). This section was small enough to search the entire keyspace in a *reasonable* amount of time, with most SuperPro envelopes it is usually only the first section one needs to get lucky with. Response 0x937E647D.

00BAD4D9: 8B 76
00BAD4DA: 7C 10
00BAD4DB: 24 66
00BAD4DC: 18 C7
00BAD4DD: 8B 46
00BAD4DE: 07 06
00BAD4DF: 3D 14
00BAD4E0: 6E 04
00BAD4E1: 61 66
00BAD4E2: 27 B8
00BAD4E3: B8 14
00BAD4E4: 75 00
00BAD4E5: 07 5F
00BAD4E6: B8 5E
00BAD4E7: F3 5B
00BAD4E8: 03 C2
00BAD4E9: 3B 18
00BAD4EA: D5 00
00BAD4EB: EB 8D
00BAD4EC: DE 7E
00BAD4ED: 3D 3C
00BAD4EE: E8 53
00BAD4EF: ED 57
00BAD4F0: DA 50
00BAD4F1: B6 E8
00BAD4F2: 75 CA
00BAD4F3: 07 97
00BAD4F4: B8 FF
00BAD4F5: 7D FF
00BAD4F6: 64 66
00BAD4F7: 7E C7
00BAD4F8: 93 46
00BAD4F9: EB 30
00BAD4FA: D0 10
00BAD4FB: 33 00
00BAD4FC: C0 66
00BAD4FD: 5F 8B
00BAD4FE: 5E 44
00BAD4FF: 5B 24
00BAD500: C2 14
00BAD501: 18 66
00BAD502: 00 89

End - Now I get an error loading import libraries, think I'm missing a few DLL's, maybe you can send me them. The program also decrypts its own Sentinel object, so there are more checks, the best strategy here is to work out what patches you need to apply, then modify the encrypted data to produce the code you need. The only problem with this is that you'll also need to fix the query checksums.

Regards

CrackZ.

sope
January 7th, 2003, 11:28
Hi CrackZ

Thanks for your time, your note and your brute force on this target.

I need to know what is the values (WORD's) starting from
0xBAD0A1 to 0xBAD144 do i need to paste it in the target ?

> Full sproRead() emulation, we patch words 0x30/0x34/0x38/0x3C all to
> 0xFFFFh and the dongle serial number to 0x3039 (12345) ;-)

I did not get your point. I have pasted the sproRead, sproQuery
emulation, do i need to change in it ?

Regards
Sope

-----
Below is the emulation i did for this target
sproFindFirstUnit

1st break sproFindFirstUnit()

00FB8EC4 CALL 00FB2CF0
00FB8EC9 MOV ESI,EAX
00FB8ECB CMP WORD PTR [ESI],7242
00FB8ED0 XOR EAX,EAX
00FB8ED2 NOP
00FB8ED3 NOP
00FB8ED4 NOP
00FB8ED5 NOP
00FB8ED6 POP ESI
00FB8ED7 POP EBX
00FB8ED8 RET 0008
00FB8EDB ADD EAX,00000000


2nd break sproRead()

00FB909B CMP WORD PTR [ESI],7242
00FB90A0 JZ 00FB90A2
00FB90A2 PUSH EBP
00FB90A3 CALL 00FB90A8
00FB90A8 POP EBP
00FB90A9 LEA EDX,[EBP+1E]
00FB90AC POP EBP
00FB90AD MOVZX ECX,WORD PTR [ESP+10]
00FB90B2 SHL ECX,1
00FB90B4 MOVZX EAX,WORD PTR [ECX+EDX]
00FB90B8 MOV EDI,[ESP+14]
00FB90BC MOV [EDI],AX
00FB90BF XOR EAX,EAX
00FB90C1 POP EDI
00FB90C2 POP ESI
00FB90C3 RET 000C
00FB90C6 JL 00FB90EC
00FB90C8 ADC AL,0B

3rd break sproQuery()
> Code Preliminary emulation routine for this :

00FB948D CMP WORD PTR [ESI],7242
00FB9492 JZ 00FB9494
00FB9494 MOV EAX,[00FAF8E4]
00FB9499 MOV EDX,[ESP+18] <--- Query from Stack
00FB949D CMP EAX,[EDX]
00FB949F JNZ 00FB94B0 <---Next Query
00FB94A1 MOV EDX,[ESP+1C] <-- response from stack
00FB94A5 MOV [EDX],EAX <-- save
00FB94A7 NOP
00FB94A8 XOR EAX,EAX
00FB94AA POP EDI
00FB94AB POP ESI
00FB94AC POP EBX
00FB94AD RET 0018

> 4th & 5th sproQuery, this time we need to handle
> GetQuery() & GetResponse()

00FB94B0 CALL 00FB1590 <--- GetQuery
00FB94B5 XOR EAX,FD0699D6 <--- xor with FD0699D6
00FB94BA MOV EDX,[ESP+18] <--- inputed query value from stack
00FB94BE CMP EAX,[EDX] <--- is same
00FB94C0 NOP
00FB94C1 NOP
00FB94C2 CALL 00FB15A0 <--- GetResponse
00FB94C7 XOR EAX,7B2309A7 <--- xor with 7B2309A7
00FB94CC MOV EDX,[ESP+1C] <--- response from stack
00FB94D0 MOV [EDX],EAX <--- store it
00FB94D2 XOR EAX,EAX
00FB94D4 POP EDI
00FB94D5 POP ESI
00FB94D6 POP EBX
00FB94D7 RET 0018

now i am doing something wrong i guess, because i am shown with a error which i have been seeing from long time.

So from this point onwards i used to manually change the flags & reach the decryption routine.

sope
January 8th, 2003, 06:41
Hi CrackZ

I reached the OEP = 715700 so i dumped the file

/pedump 400000 315700 C:\dmp.exe <enter>

Now followed the code i found below codes

(1) SproFindFirstUnit

004FB0C5 loc_4FB0C5:
004FB0C5 push 0F580h ; <--- Developer ID
004FB0CA push offset unk_75C7AC ; <--- Rnbospro Handle
004FB0CF call sub_7053D0

So i emulated as above.

(2) I found below Querydata & good response being moved.

Querydata being moved for sproQuery

004FB0F1 loc_4FB0F1:
004FB0F1 mov byte ptr [ebp+var_5C], 0B6h
004FB0F5 mov byte ptr [ebp+var_5C+1], 3Ch
004FB0F9 mov byte ptr [ebp+var_5C+2], 0A3h
004FB0FD mov byte ptr [ebp+var_5C+3], 0BFh
004FB101 mov byte ptr [ebp+var_58], 0A0h
004FB105 mov byte ptr [ebp+var_58+1], 0B2h
004FB109 mov byte ptr [ebp+var_58+2], 93h
004FB10D mov byte ptr [ebp+var_58+3], 0C3h

Good response being moved

004FB111 mov byte ptr [ebp+var_CC], 14h
004FB118 mov byte ptr [ebp+var_CC+1], 0EDh
004FB11F mov byte ptr [ebp+var_CC+2], 0Bh
004FB126 mov byte ptr [ebp+var_CC+3], 0FDh
004FB12D mov byte ptr [ebp+var_CC+4], 0AFh
004FB134 mov byte ptr [ebp+var_CC+5], 0F5h
004FB13B mov byte ptr [ebp+var_CC+6], 8
004FB142 mov byte ptr [ebp+var_CC+7], 96h

SproQuery emulation 026h, 3Eh, 0Ch, 24h

004FB149 push 8 <--- length
004FB14B lea eax, [ebp+var_D4+4]
004FB151 push eax <--- response32
004FB152 lea ecx, [ebp+var_94]
004FB158 push ecx <--- response
004FB159 lea edx, [ebp+var_5C]
004FB15C push edx <---queryData
004FB15D push 26h <--- cell address
004FB15F push offset unk_75C7AC <--- packet handle
004FB164 call sub_705990 <--- RNBOsproQuery

So i emulated the sproquery show below

007059AD CMP WORD PTR [ESI],7242
007059B2 JZ 007059B4
007059B4 MOV EDX,[ESP+1C] <-- response from stack
007059B8 MOV DWORD PTR [EDX],FD0BED14 <--- first 4 bytes
007059BE MOV DWORD PTR [EDX+04],9608F5AF <--- remaining 4 bytes
007059C5 XOR EAX,EAX
007059C7 POP EDI
007059C8 POP ESI
007059C9 POP EBX
007059CA RET 0018 <--- ret

New we have the below compare

004FB1EE push 8 <--- length
004FB1F0 lea ecx, [ebp+var_94]
004FB1F6 push ecx <--- our response
004FB1F7 lea edx, [ebp+var_CC]
004FB1FD push edx <--- good response
004FB1FE call sub_70FBA0 <--- compare it
004FB203 add esp, 0Ch
004FB206 test eax, eax <-- all ok

compare is checked 3 times.

Next we reach the SproRead() 0Fh, 0Eh so i emulated show below

007055BB CMP WORD PTR [ESI],7242
007055C0 JZ 007055C2
007055C2 PUSH EBP
007055C3 CALL 007055C8
007055C8 POP EBP
007055C9 LEA EDX,[EBP+1E]
007055CC POP EBP
007055CD MOVZX ECX,WORD PTR [ESP+10]
007055D2 SHL ECX,1
007055D4 MOVZX EAX,WORD PTR [ECX+EDX]
007055D8 MOV EDI,[ESP+14]
007055DC MOV [EDI],AX
007055DF XOR EAX,EAX
007055E1 POP EDI
007055E2 POP ESI
007055E3 RET 000C
007055E6 JL 0070560C

After this i reach a point in program offset 0x4FBD80 we find similar type Querydata (shown above) being moved & good response so i applied the same emulation shown above for SproQuery() & same 3 times compare & then same sproread().

Now i get runtime error page faults 0x45FA14, i guess i am doing
something wrong somewhere OR something with import table program i dumped is not properly rebuilded OR my SproRead not proper i need to find the perfect dongle word put it at that offset. I got stuck again

Can u give me hints, i am so close to finish it after a long time!

Regards
Sope