Log in

View Full Version : WIBU WkbCrypt2 (WITH dongle)


fritzFS
August 14th, 2006, 20:10
Hello,

I've started to analyze this target and I've removed dongle checks ...
When I run the application, I tried to use some function in it and then it crashes.

So, back to work.

Every function has this kind of block inside and there it crashes.

Code:

.text:00404D8F mov edx, [ebx] ; i.e. 412168
.text:00404D91 push esi
.text:00404D92 push edi
.text:00404D93 mov ecx, ebx
.text:00404D95 call dword ptr [edx+78h] ; i.e. 402410 - with dongle


When there's no dongle, call at 404D95 tries to call invalid address.

412168 is inside .rdata section.

That section differs, when it's looked just on the hard drive and when looked in the running (with dongle) process.

From the hard drive:
Code:

74 70 01 00 60 70 01 00 4A 70 01 00 ...


From the running process:
Code:

44 61 34 77 CE AD 38 77 8E AE 38 77 ...


I tried dumping the running process and run that file, but crashes right away.
After that, I've looked in target's directory and there's plenty of DLL's ...
Also, .rdata sections in ALL DLL's differs, those that are loaded and those from the hard drive.

I've read mueller5321 thread about wkcrypt issue, but I'm still stuck.

Also, I've read SnakeByte's & CrackZ tutorial about Wibu dongle.

Is there anyone with similiar expirience?

Sab
August 14th, 2006, 22:58
I really am not sure of your actual approach, or in fact what the hell you are saying, however, I know this dongle quite well. I am guessing that api's are still called via the wkwin32.dll. In that case, the method for reversing your application can be really easy by simply emulating the dll itself. Infact, you wont even need to recode the dll, you can use the existing one and hexedit it. I would start by opening the dll and exe. Then find the apis used in your application with a signature or it may just be in the import table in plaintext. Then, go to the wkwin32.dll and patch out the calls it uses. Example..

Now in order to kill the dongle you gotta understand it... so a look at a couple of the apis...

WkbListPort2( HWKB_LOCAL, WKB_LEVEL1, PortName, &BoxList, sizeof( BoxList )
WkbListBox2( HWKB_LOCAL, WKB_LEVEL1 | WKB_LIST_DATA, PortName, BoxList.awkbsr, &BoxData, sizeof( BoxData )
hEntry = WkbOpen2( HWKB_LOCAL, WKB_STDCTRL | WKB_OPEN_FIND | WKB_VERSION2,
PortName,
BoxData.awkbbxe[ EntryIndex ].ulFirmCode,
BoxData.awkbbxe[ EntryIndex ].ulUserCode,
NULL );
Okay so from our sample we see 3 easy apis. If you see the api guide on Crackz site you should see most just need to return TRUE.
example:
INT WKAPIENTRY _export WkbClose2( HWKBENTRY hwkbe )
{
return TRUE;
}

The only api's you would have to be concenred with , as in all dongles are read and crypt. So what I would do in your case is find out how its used. Example, for wkcrypt2 go ahead and just
INT WKAPIENTRY _export WkbCrypt2( HWKBENTRY hwkbe, ULONG flCtrl, VOID FAR * pvDest,VOID FAR * pvCtrl, UINT cbSrc, UINT FAR * pcbDest )

__asm{int 3}
return TRUE;

Once you do that you can break on the api and look at all the arguments sent. You will also be able to backtrace to the call and see what reason it is calling the crypt for. you might want to be careful, wkbcrypt2 is an actual encryption call to feal-n. The application might be using it to decrypt files, or if its packed, decrypt a section of its own executable. I take it your app is not packed, or you would not have gotten it to run anyways.

Once you understand the call to wkbcrypt2 from your application you should be able to determine what value it wants back. After determining the value simply just hardcode the return by doing a table emulator. OR, let the call go with success through the dll, and hardcode the value in the .exe to pass. So in the .dll itll just return true, but in the .exe you do cmp eax, val patch. Btw, if you do not have a dongle, be cautious that if you hardcode a good jump in the .exe it is not a crucial part of the applications functionality (generally not).

Anyways, thast hte best way to do it. Otherwise, you are going to be running around a .exe messing up the stack, return values, u name it. Just emulate it at the core , so that no matter how many calls there are in the .exe its nullified. Have fun.

fritzFS
August 15th, 2006, 08:09
Hello Sab,

yes, the communication with dongle is via wkwin32.dll.

I was thinking of that approach also, but then I saw 'WIBU-KEY API' and most of those API's return handle of something and NULL on error.

Anyway, as I understood it, there's no simple TRUE or FALSE ...

So, I tried to patch it on 'higher level', inside application's executable file and his DLL's.

I'll try patching it in wkwin32.dll now, as you said, and report the results here!

Sab, thank you for your post!

naides
August 15th, 2006, 08:43
Hi Fritz:

Typically, when an API call returns TRUE, it means it returns the value 1 in EAX.

When an API returns FALSE, it returns the value 0 or sometimes the value FFFFFFFF in EAX.

Of course if you let the API try to comunicate with the dongle and there is none connected an error will occur.

You may want to patch the code at wkwin32.dll to just write an 00000001 in eax, balance the stack if necessary, and return to your app EXE or DLL module, therefore bypassing most "Dongle are you there?" Checks.

When the APP expects something else from the Dongle, a specific value, it will be written usually to some buffer pointed in the stack.

fritzFS
August 15th, 2006, 09:07
Hello Naides and Sab,

I've done more tracing with WKWIN32.DLL and this is my notes:

While application is loading, this is the WIBU calls and their return value (address is just an address of last instruction in function in wkwin32.dll)

Code:

WkbGetVersion2
- (0x2000295E) EAX = 0x4602

WkbQueryStatus2
- (0x20002A01) EAX = 0x4

WkbAccess2
- (0x20001253) EAX = 0x10

WkbOpen2
- (0x20003BC2) EAX = 0x11

WkbQuerySystem2
- (0x200022A8) EAX = 0xFFFFFFFE
EBX = 0x1
ECX = 0x0
EDX = 0x14

// REPEATS 21 TIMES
WkbSelect2
- (0x20004522) EAX = 0x1

WkbCrypt2
- (0x20004F0F) EAX = 0x1

WkbUnSelect2
- (0x20004D1A) EAX = 0x1

// END OF LOOP


But, I think this can be a real problem since additional calls are made while the application is used ... see below :

When in application and I try to use one of it's functions, following calls are also logged:

WkbSelect2
WkbCrypt2
WkbSelect2
WkbCrypt2
WkbUnSelect2

fritzFS
August 15th, 2006, 09:22
Also, about WkbCrypt2 ...

Inside WkbCrypt2 in WKWIN32.DLL :

.text:20004D5A mov ebx, [esp+4+flCtrl] ; EBX = 0x101

I have trouble understanding this 0x101 with my WIBU-KEY API version of document.

Is it : WKB_LEVEL_1 | WKB_CRYPT_COPY ?

fritzFS
August 15th, 2006, 10:05
Hello, I've done more tracing in WkbCrypt2 (with dongle) and this is the results:

Code:


.text:20004D20 ; int __stdcall WkbCrypt2(int hwkbe,int flCtrl,int pvDest,LPVOID pvCtrl,UINT cbSrc,int pcbDest)
.text:20004D20 public WkbCrypt2
.text:20004D20 WkbCrypt2 proc near ; CODE XREF: sub_20006E90+27p
.text:20004D20 ; sub_20008F00+CEp ...
.text:20004D20
.text:20004D20 hwkbe = dword ptr 10h
.text:20004D20 flCtrl = dword ptr 14h
.text:20004D20 pvDest = dword ptr 18h
.text:20004D20 pvCtrl = dword ptr 1Ch
.text:20004D20 cbSrc = dword ptr 20h
.text:20004D20 pcbDest = dword ptr 24h
.text:20004D20
.text:20004D20 push ebx
.text:20004D21 push ebp
.text:20004D22 push esi
.text:20004D23 lea eax, [esp+pvDest] ; EAX = 0x12EE64
.text:20004D27 push edi
.text:20004D28 push eax
.text:20004D29 call sub_20005D40
.text:20004D2E test eax, eax ; EAX = 1
.text:20004D30 jz loc_20004F40 ; not taken
.text:20004D36 lea ecx, [esp+4+pvCtrl] ; ECX = 0x12EE68
.text:20004D3A push ecx
.text:20004D3B call sub_20005D40
.text:20004D40 test eax, eax ; EAX = 1
.text:20004D42 jz loc_20004F40 ; not taken
.text:20004D48 lea edx, [esp+4+pcbDest] ; EDX = 0x12EE70
.text:20004D4C push edx
.text:20004D4D call sub_20005D40
.text:20004D52 test eax, eax ; EAX = 1
.text:20004D54 jz loc_20004F40 ; not taken
.text:20004D5A mov ebx, [esp+4+flCtrl] ; EBX = 0x101
.text:20004D5E mov eax, [esp+4+hwkbe] ; EAX = 0x11
.text:20004D62 push ebx
.text:20004D63 push eax
.text:20004D64 call sub_20007E10
.text:20004D69 test eax, eax ; EAX = 1
.text:20004D6B jz loc_20004F40 ; not taken
.text:20004D71 mov ecx, [esp+4+pvDest] ; ECX = 0x12EF98
.text:20004D75 xor esi, esi
.text:20004D77 test bl, 1
.text:20004D7A mov ebx, [esp+4+cbSrc] ; EBX = 0x38
.text:20004D7E mov [esp+4+hwkbe], ecx
.text:20004D82 jz short loc_20004DC4 ; not taken
.text:20004D84 mov eax, [esp+4+pvCtrl] ; EAX = 0x12EF34
.text:20004D88 push ebx ; ucb
.text:20004D89 push eax ; lp
.text:20004D8A mov [esp+0Ch+hwkbe], eax
.text:20004D8E call sub_20007F70
.text:20004D93 test eax, eax ; EAX = 1
.text:20004D95 jz loc_20004F40 ; not taken
.text:20004D9B
.text:20004D9B loc_20004D9B: ; CODE XREF: WkbCrypt2+AAj
.text:20004D9B mov edi, [esp+4+flCtrl] ; EDI = 0x101
.text:20004D9F
.text:20004D9F loc_20004D9F: ; CODE XREF: WkbCrypt2+BEj
.text:20004D9F and edi, 0F0h
.text:20004DA5 push ebx ; EBX = 0x38
.text:20004DA6 mov ebp, edi
.text:20004DA8 and ebp, 70h
.text:20004DAB cmp ebp, 10h
.text:20004DAE jnz short loc_20004DE0; taken

.text:20004DE0 loc_20004DE0: ; CODE XREF: WkbCrypt2+8Ej
.text:20004DE0 mov eax, [esp+8+pvDest] ; EAX = 0x12EF98
.text:20004DE4 push eax ; lp
.text:20004DE5 call sub_20007FA0
.text:20004DEA test eax, eax ; EAX = 1
.text:20004DEC jz loc_20004F40 ; not taken
.text:20004DF2
.text:20004DF2 loc_20004DF2: ; CODE XREF: WkbCrypt2+A2j
.text:20004DF2 test ebp, ebp ; EBP = 0
.text:20004DF4 jz short loc_20004E11 ; taken

.text:20004E11 loc_20004E11: ; CODE XREF: WkbCrypt2+D4j
.text:20004E11 ; WkbCrypt2+D9j
.text:20004E11 test esi, esi ; ESI = 0
.text:20004E13 jz loc_20004ED7 ; taken

.text:20004ED7 loc_20004ED7: ; CODE XREF: WkbCrypt2+F3j
.text:20004ED7 mov eax, dword_200175A4 ; EAX = 0x1432064
.text:20004EDC mov ecx, [eax] ; ECX = 0x38
.text:20004EDE test ecx, ecx ; ECX = 1432168
.text:20004EE0 jz short loc_20004F12 ; not taken
.text:20004EE2 test esi, esi ; ESI = 0
.text:20004EE4 jz short loc_20004EEB ; taken

.text:20004EEB loc_20004EEB: ; CODE XREF: WkbCrypt2+1C4j
.text:20004EEB xor eax, eax
.text:20004EED
.text:20004EED loc_20004EED: ; CODE XREF: WkbCrypt2+1C9j
.text:20004EED mov edx, [esp+4+pcbDest] ; EDX = 0x12EE94
.text:20004EF1 push edx ; int
.text:20004EF2 mov edx, [esp+8+pvDest] ; EDX = 0x12EF98
.text:20004EF6 push edi ; int
.text:20004EF7 push eax ; lp
.text:20004EF8 mov eax, [esp+10h+hwkbe] ; EAX = 0x12EF34
.text:20004EFC push esi ; int
.text:20004EFD push ebx ; int
.text:20004EFE push eax ; int
.text:20004EFF push edx ; int
.text:20004F00 push ecx ; int
.text:20004F01 call sub_20004350 ; RET : EAX = 0x38, EDX = 0x32
.text:20004F06 call sub_20007EF0 ; RET : EAX = 1, ECX = 0, EDX = 0
.text:20004F0B pop edi
.text:20004F0C pop esi
.text:20004F0D pop ebp
.text:20004F0E pop ebx
.text:20004F0F retn 18h


fritzFS
August 15th, 2006, 11:06
Silly me ..
I've re-read the WIBU-KEY API and noticed that encryption/decryption algoritam is selected by WkbSelect2 API, not WkbCrypt2 so ... here it goes, I traced WkbSelect2 API also ...

Code:

.text:200044B0 WkbSelect2 proc near ; CODE XREF: sub_20006E60+19p
.text:200044B0 ; sub_20006EF0+75p ...
.text:200044B0
.text:200044B0 hwkbe = dword ptr 4
.text:200044B0 flCtrl = dword ptr 8
.text:200044B0 ulSelectCode = dword ptr 0Ch
.text:200044B0 pvCtrl = dword ptr 10h
.text:200044B0
.text:200044B0 lea eax, [esp+pvCtrl]
.text:200044B4 push ebx
.text:200044B5 push eax
.text:200044B6 call sub_20005D40
.text:200044BB test eax, eax
.text:200044BD jz short loc_2000451C
.text:200044BF mov ebx, [esp+4+flCtrl] ; EBX = 0x110
.text:200044C3 mov ecx, [esp+4+hwkbe] ; ECX = 0x11
...


0x110 - is that "WKB_LEVEL1 | WKB_SEL_KNUTH20 " ?

FoxB
August 15th, 2006, 14:05
Your sw used WIBU envelope?

fritzFS
August 15th, 2006, 14:24
No, I cannot find any signatures in PE sections ...
And I patched Is_Dongle_Here check and the application runs, so there's no envelope ... Just WkbCrypt2 ...

Sab
August 15th, 2006, 20:11
okay fritz.. i usually dont help beyond my initial post but I feel this post might help others and u did a lot of documenting... anyways.. here goes:

WkbGetVersion2
- (0x2000295E) EAX = 0x4602

WkbQueryStatus2
- (0x20002A01) EAX = 0x4

WkbAccess2
- (0x20001253) EAX = 0x10

WkbOpen2
- (0x20003BC2) EAX = 0x11

WkbQuerySystem2
- (0x200022A8) EAX = 0xFFFFFFFE
EBX = 0x1
ECX = 0x0
EDX = 0x14

// REPEATS 21 TIMES
WkbSelect2
- (0x20004522) EAX = 0x1

WkbCrypt2
- (0x20004F0F) EAX = 0x1

WkbUnSelect2
- (0x20004D1A) EAX = 0x1

// END OF LOOP
Either code a dll (which is a bit of work) and do something like..
INT WKAPIENTRY _export WkbClose2( HWKBENTRY hwkbe )
{
return TRUE;
}

or i think better for you..
Open wkwin32.dll get its export addresses, then in hiew patch out using this style..:

wkbOpen2 :
push ebp
mov ebp, esp
xor eax, eax
mov eax, 11h
pop ebp
retn 18h
----------------------------------

WkbClose2:
push ebp
mov ebp, esp
mov eax, 1
pop ebp
retn 4

---------------------------------
WkbGetLastError
push ebp
mov ebp, esp
xor eax, eax // note return 0 on this api
pop ebp
retn
--------------------------------
WkbQueryEntry2:
push ebp
mov ebp, esp
mov eax, 1
pop ebp
retn 10h
---------------------------------
Do this for all api below:
wkbcrypt2
wkbselect2
wkbunselect2
WkbQuerySystem2
WkbGetVersion2
WkbQueryStatus2
WkbAccess2
WkbOpen2

After you do that.. then set a int3 inside of wkbcrypt2 and break on it each time. THe value 0x101 you seen is from wkbselect, which sets the mode of encrypt or decrypt. All you need to do is just look at the values going in, the query value, and the values going out, the response value. If you do not have a dongle, then you have to figure out what the response values are. Once you figure out the values in/out you can just do something inside the dll like..

WkbCrypt2 :

push ebp
mov ebp, esp
push ebx
push esi
push edi
mov edi, [ebp+1Ch]
mov esi, [ebp+18h]
mov ebx, [ebp+10h]
mov eax, [ebp+14h]
xor eax, eax
int 3 // once you figured out all the ins/out values
inc eax
pop edi
pop esi
pop ebx
pop ebp
retn 18h

now you can fill in where xor eax, eax ->inc eax is with something like...
for (int i = 0; i<21; i++)
if (QueryValue == tableOfQueries[I])
responseval = tableOfResponses[I];

as to say: find the corresponding response code that goes with the query value you found through debugging. Okay start hunting the in/out responses from wkbcrypt, and then get back to us.

Woodmann
August 15th, 2006, 21:04
Sab kicks ass

Woodmann

NeOXOeN
August 16th, 2006, 20:19
yes i agreee-... nice info...

bye

FoxB
August 17th, 2006, 02:59
Quote:
[Originally Posted by Sab].....
for (int i = 0; i<21; i++)
if (QueryValue == tableOfQueries[I])
responseval = tableOfResponses[I];
...



Valid only for static tableOf.., imho.

WBR

fritzFS
August 17th, 2006, 03:08
Thank you Sab,

For now, I've modified WKWIN32.DLL in all mentioned functions except WkbCrypt2. I'll start to work on it as soon as I get home (2 days).

I'll post my results here!

Sab
August 17th, 2006, 12:34
Yes, its designed for static table in everyones opinion ( : because by his description of loop of 21 queries, and general implementation pattern, wibu usually uses static query values to dongle and then returns a expected result, that is a given. BUT if he is in the case where the developer is unique and the dongle is not used statically but dynamically queried, i.e. Rng(32)->Query Wkbcrypt2(Query, Response), he would have to figure out how the responses are used.. i.e. used to decrypt files etc. But that is a very very rare case. Of 20 wibus ive seen 2 use it and of 100+ dongles random dongles ive seen 1 other use it. These were speciality protectionists in the audio scene. If he is in that case, he will require a full emulator by actually implementing fealn + solving the internal key, which I dont think he is capable of(no offense)/ OR, find a bug in rng/backup dongle website service. But its almost~ certain that is not the case , the query values are going to be static because of the loop. Sounds to me like the app builds a loop of 21 queries and checks them all somewhere in the app just like 99% of the apps out there. fritz, i hope to see your results soon.

fritzFS
August 27th, 2006, 19:21
Hello Sab,

Sorry for my absent, I came back as soon as I could.

Ok, I've analyzed it more and here are the results:

WkbCrypt2 (operating with 56dec bytes - cbSrc parameter)
=> means input data
<= means output data

Code:

=> 96 B2 A A7 F4 F4 87 81 87 87 86 F4 CF E3 90 93 DC DA D2
C7 7C 5A 5A 49 35 22 0F 05 F3 E6 9D 44 32 6C 08 39 4C BB C3
C3 E0 A0 C6 55 66 9A 67 61 EC D8 BD 13 C8 01 73 CF (HEX)
<= EXPERT00032256EXPERT00008224EXPERT00001792EXPERT00057742 (CHAR)

=> D0 5E 56 4B 2C 2C C1 C7 929B 93 2C E9 6F 18 13 6C 6A F3
E1 64 76 76 8F C7 40 EB EB DF CA 4B B2 DE F4 90 6F 9D 16 45
45 D0 B6 5C 04 6A AA 8B 17 6F E8 3B F5 06 13 AC 78 (HEX)
<= EXPERT00008192EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> EC 96 9E 83 BC BC FD FB 5F 5F 5F BC 6D 17 62 62 4C 4A 70
65 95 EE EE CB 21 01 B2 B1 C7 D2 C7 56 16 E4 80 A3 11 0A 39
39 F0 BA 2A 3D E2 8A C3 F3 2B 08 47 A9 BC DF 3C 58 (HEX)
<= EXPERT00000000EXPERT00016512EXPERT00004096EXPERT00000002 (CHAR)

=> 22 CA C2 DF 04 04 33 35 31 34 35 04 C3 8B F6 F6 3C 3A DE
CB A8 32 32 05 AD E4 5B 5B DB CE 89 D8 0A 5C 38 CD 58 90 34
37 80 34 94 04 FE FA 9F 5D 23 78 49 47 60 B6 80 2D (HEX)
<= EXPERT00045088EXPERT00042240EXPERT00032780EXPERT00065472 (CHAR)

=> CE E2 EA F7 54 54 DF D9 0D 0D 0D 54 B7 53 26 26 9C 9A AA
BF 1C 4A 4A 91 59 A0 35 35 E3 F6 95 2C E2 8C E8 B1 43 AA 9B
9B 20 A8 24 7C D6 5A B7 49 31 18 E5 6B BA 8D D4 88 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> 86 D2 DA C7 34 34 97 91 75 75 75 34 9F C3 B6 B6 5C 5A 82
97 3C BA BA 79 61 20 7D 7D D3 C6 0D 14 92 2C 48 89 DB 9A D3
D3 60 30 04 1C 86 1A 87 D1 99 58 AD 23 2A F5 B4 48 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> 98 6E 66 7B 4C 4C 89 8F 2C 29 28 4C 01 FF 82 8C AC AA 1C
09 42 06 06 A7 BA C3 26 26 EF FA 53 CA 2E 54 30 97 86 26 8D
8D 90 AE 75 67 BA EA BB 0F 07 A8 F3 BD 94 AB CC BA (HEX)
<= EXPERT00032768EXPERT00065535EXPERT00000339EXPERT00002002 (CHAR)

=> B4 A6 AE B3 DC DC A5 A3 D2 D2 D1 DC 85 A7 D7 D1 8C 8A 98
8D F2 FE FE E3 9E 83 8A 8A D7 C2 CF EE 66 44 20 2B 1C 1B 67
61 B0 B2 C9 17 32 CA F3 EB C3 C8 1F 51 CC 54 5C 98 (HEX)
<= EXPERT00065535EXPERT00065535EXPERT00065535EXPERT00000032 (CHAR)

=> 92 6A 62 7F 44 44 44 83 85 21 21 21 44 13 EB 9E 9E BC BA
0E 1B 6C 12 12 B5 5D E0 C9 C9 3B 2E B9 28 EA 1C 78 DD 6F F2
47 47 C4 D4 CC 1E 7A 3F 8D 55 F8 39 D7 42 A1 C4 A8 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> B0 1E 16 0B AC AC A1 A7 73 73 73 AC C9 AF DA DA 6C 6A D4
C1 E4 B6 B6 EF 27 40 4B 4B 1F 0A EB 52 1E 74 10 CF 3D 56 E5
E5 D0 D6 DC 84 2A AA 4B 37 4F E8 9B 15 46 F3 2C 78 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> EE 22 2A 37 D4 D4 FF F9 2D 2D 2D D4 D7 13 66 66 9C 9A CA
DF 9C 0A 0A 31 F9 A0 D5 D5 A3 B6 F5 8C A2 0C 68 51 A3 6A FB
FB 20 88 A4 FC 16 5A F7 29 51 18 85 4B 7A AD 54 88 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> 50 5E 56 4B 2C 2C 41 47 13 13 13 2C 69 6F 1A 1A 6C 6A 74
61 64 76 76 0F 47 40 6B 6B DF CA CB 32 DE F4 90 EF 1D 16 C5
C5 D0 36 5C 04 6A AA 8B 97 EF E8 BB 75 06 93 AC 78 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> 2E A2 AA B7 D4 D4 3F 39 6D 6D 6D D4 17 93 E6 E6 9C 9A 0A
1F 9C 8A 8A 71 39 A0 15 15 23 36 B5 4C 22 0C 68 91 63 EA BB
BB 20 48 A4 FC 96 5A 77 E9 91 18 C5 0B FA ED 54 88 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000 (CHAR)

=> 52 EA E2 FF 44 44 43 45 E1 E1 E1 44 D3 6B 1E 1E BC BA CE
DB 6C 92 92 75 1D E0 89 89 BB AE F9 68 6A 1C 78 9D AF 72 87
87 00 04 D6 CD 9E 7A BF CD 15 F8 F9 17 CB 62 C7 A8 (HEX)
<= EXPERT00000000EXPERT00000000EXPERT00000012EXPERT00000339 (CHAR)

=> AE A2 AA B7 D4 D4 BF B9 EA EF EC D0 0A 00 E7 E5 BC BA CE
DB 6C 92 92 75 1D E0 89 89 BB AE F9 68 6A 1C 78 9D AF 72 87
87 00 04 D6 CD 9E 7A BF CD 15 F8 F9 18 CB 62 C7 A8 (HEX)
<= 45 50 58 45 30 30 54 52 37 32 31 34 C5 D6 31 33 74 72 01
14 C0 28 28 B4 94 70 2C 2C DD C8 94 E1 78 20 44 DE 7C A8 8C
8C 78 89 42 01 5C 72 8D F4 34 D0 8C AC 01 3F A3 10 (HEX) - NOT CLEAN AS BEFORE, SO THAT'S WHY HEX

...


I don't understand how can output data be equal in cases where input data isn't. (check "EXPERT00000000EXPERT00000000EXPERT00000000EXPERT00000000" )

After the program has been loaded, now it breaks when i try to use one of its function (File->Open inside target program).
Code:

cbSrc = 0X15
flCtrl = 0X101 (still, same as before)
pvCtrl = "CTTQVOJHOTYBXNJJFTHB"
=> 0BAADF00D 0BAADF00D 0BAADF00D ...
<= 2E FE FE E9 1C 1E 30 29 6B 70 7D 1B 99 B4 B0 A6 EA E0 87 95 70


(Another target function File->New breaks on WkbCrypt2)
Code:

cbSrc = 0X15
flCtrl = 0X101 (still, same as before)
pvCtrl = "EUZFYBIOYPOBPSHQOUBI"
=> 0BAAD F00D 0BAAD F00D 0BAADF00D ...
<= 65 98 97 87 CB CD 61 7A A7 AA B5 DD F6 0E 15 16 41 4A F2 E8 64


It doesnt break on any target function, seems that developer set them random on couple of functions. So far, I found 4 places.

FoxB
August 28th, 2006, 11:34
4fritzFS: you not help table. imho

Sab
August 29th, 2006, 19:26
Looks like a reasonable implementation. Can you rip & paste the functions that call to wkbcrypt2 (xrefs), with the parameters that are pushed. Also , rip the xrefs to wkbselect2 and paste. Looks like they binded function to file/save or open ruitine. But, still crackable anyways. Paste those infos, and I will take a look at wkapi again (been about 4 years) to see exactly whats going on.

fritzFS
August 30th, 2006, 06:27
Sab,

this is a routine that's called when application is running:

inside this, it calles WkbSelect2, WkbCrypt2 and WkbUnSelect2 21 times:

Code:

...
.text:100018F5 cmp [ebp+arg_8], 0Ah
.text:100018F9 jg short loc_1000196F
.text:100018FB push ebx
.text:100018FC push dword ptr [esi+188h]
.text:10001902 push 110h
.text:10001907 push dword ptr [esi+2Ch]
.text:1000190A call WkbSelect2
.text:1000190F mov edi, eax
.text:10001911 test edi, edi
.text:10001913 jz short loc_10001943
.text:10001915 lea eax, [ebp+arg_C]
.text:10001918 push eax
.text:10001919 push [ebp+arg_14]
.text:1000191C push [ebp+arg_10]
.text:1000191F push [ebp+arg_18]
.text:10001922 push 101h
.text:10001927 push dword ptr [esi+2Ch]
.text:1000192A call WkbCrypt2
.text:1000192F mov edi, eax
.text:10001931 test edi, edi
.text:10001933 jz short loc_10001943 ; nop
.text:10001935 push dword ptr [esi+2Ch]
.text:10001938 call WkbUnSelect2
.text:1000193D mov edi, eax
.text:1000193F test edi, edi
.text:10001941 jnz short loc_10001968
.text:10001943
.text:10001943 loc_10001943: ; CODE XREF: sub_100018C5+4Ej
.text:10001943 ; sub_100018C5+6Ej
.text:10001943 cmp [ebp+arg_0], 0
.text:10001947 jz short loc_1000195D
.text:10001949 call WkbGetLastError
.text:1000194E cmp eax, 7
.text:10001951 jnz short loc_1000195D
.text:10001953 mov eax, [ebp+arg_4]
.text:10001956 push 1
.text:10001958 pop edi
.text:10001959 mov [eax], edi
.text:1000195B jmp short loc_10001968
.text:1000195D ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:1000195D
.text:1000195D loc_1000195D: ; CODE XREF: sub_100018C5+82j
.text:1000195D ; sub_100018C5+8Cj
.text:1000195D push 0C8h ; dwMilliseconds
.text:10001962 call ds:Sleep
.text:10001968
.text:10001968 loc_10001968: ; CODE XREF: sub_100018C5+7Cj
.text:10001968 ; sub_100018C5+96j
.text:10001968 inc [ebp+arg_8]
.text:1000196B test edi, edi
.text:1000196D jz short loc_100018F5
...


Except this function, there is two more that calls WkbCrypt2 :

Code:

.text:10001985 push ebp
.text:10001986 mov ebp, esp
.text:10001988 mov edx, [ebp+arg_4]
.text:1000198B push esi
.text:1000198C mov esi, [ebp+arg_0]
.text:1000198F cmp word ptr [esi+14h], 0
.text:10001994 mov [esi+188h], edx
.text:1000199A jnz short loc_100019A6
.text:1000199C and byte ptr [esi+16h], 0
.text:100019A0 mov word ptr [esi+14h], 1
.text:100019A6
.text:100019A6 loc_100019A6: ; CODE XREF: sub_10001985+15j
.text:100019A6 lea eax, [esi+8]
.text:100019A9 mov ecx, 110h
.text:100019AE push eax
.text:100019AF push edx
.text:100019B0 push ecx
.text:100019B1 mov [eax], ecx
.text:100019B3 push dword ptr [esi+2Ch]
.text:100019B6 call WkbSelect2
.text:100019BB test eax, eax
.text:100019BD jge short loc_100019DA
.text:100019BF lea ecx, [ebp+arg_4]
.text:100019C2 push ecx
.text:100019C3 push eax
.text:100019C4 call sub_1000108B
.text:100019C9 pop ecx
.text:100019CA test eax, eax
.text:100019CC pop ecx
.text:100019CD jz short loc_10001A1C
.text:100019CF xor eax, eax
.text:100019D1 cmp [ebp+arg_4], 1
.text:100019D5 setz al
.text:100019D8 test eax, eax
.text:100019DA
.text:100019DA loc_100019DA: ; CODE XREF: sub_10001985+38j
.text:100019DA jz short loc_10001A1C
.text:100019DC lea eax, [ebp+arg_0]
.text:100019DF mov dword ptr [esi+50h], 1
.text:100019E6 push eax
.text:100019E7 push [ebp+arg_C]
.text:100019EA push [ebp+arg_8]
.text:100019ED push [ebp+arg_10]
.text:100019F0 push 101h
.text:100019F5 push dword ptr [esi+2Ch]
.text:100019F8 call WkbCrypt2
.text:100019FD test eax, eax
.text:100019FF jge short loc_10001A1A
.text:10001A01 lea ecx, [ebp+arg_4]
.text:10001A04 mov [esi+48h], eax
.text:10001A07 push ecx
.text:10001A08 push eax
.text:10001A09 call WkbIsComplete
.text:10001A0E test eax, eax
.text:10001A10 jz short loc_10001A20
.text:10001A12 and dword ptr [esi+48h], 0
.text:10001A16 cmp [ebp+arg_4], 0
.text:10001A1A
.text:10001A1A loc_10001A1A: ; CODE XREF: sub_10001985+7Aj
.text:10001A1A jnz short loc_10001A2F
.text:10001A1C
.text:10001A1C loc_10001A1C: ; CODE XREF: sub_10001985+48j
.text:10001A1C ; sub_10001985:loc_100019DAj
.text:10001A1C xor eax, eax
.text:10001A1E jmp short loc_10001A36
.text:10001A20 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:10001A20
.text:10001A20 loc_10001A20: ; CODE XREF: sub_10001985+8Bj
.text:10001A20 call WkbGetLastError
.text:10001A25 sub eax, 40h
.text:10001A28 neg eax
.text:10001A2A sbb eax, eax
.text:10001A2C inc eax
.text:10001A2D jmp short loc_10001A36


and last one:

Code:

.text:10001A39 push ebp
.text:10001A3A mov ebp, esp
.text:10001A3C push ecx
.text:10001A3D push ebx
.text:10001A3E push esi
.text:10001A3F xor ebx, ebx
.text:10001A41 push edi
.text:10001A42 push ebx ; time_t *
.text:10001A43 call _time
.text:10001A48 mov esi, [ebp+arg_0]
.text:10001A4B pop ecx
.text:10001A4C mov ecx, [ebp+arg_4]
.text:10001A4F push 1
.text:10001A51 and eax, 0FFFFh
.text:10001A56 pop edi
.text:10001A57 mov [esi+188h], eax
.text:10001A5D cmp [ecx], edi
.text:10001A5F jnz short loc_10001A6E
.text:10001A61 or eax, 0A0000000h
.text:10001A66 mov [esi+188h], eax
.text:10001A6C mov [ecx], ebx
.text:10001A6E
.text:10001A6E loc_10001A6E: ; CODE XREF: sub_10001A39+26j
.text:10001A6E cmp [esi+14h], bx
.text:10001A72 lea ecx, [esi+8]
.text:10001A75 mov eax, 110h
.text:10001A7A mov [ecx], eax
.text:10001A7C jnz short loc_10001A86
.text:10001A7E and byte ptr [esi+16h], 0
.text:10001A82 mov [esi+14h], di
.text:10001A86
.text:10001A86 loc_10001A86: ; CODE XREF: sub_10001A39+43j
.text:10001A86 push ecx
.text:10001A87 push dword ptr [esi+188h]
.text:10001A8D push eax
.text:10001A8E push dword ptr [esi+2Ch]
.text:10001A91 call WkbSelect2
.text:10001A96 cmp eax, ebx
.text:10001A98 jge short loc_10001AB4
.text:10001A9A lea ecx, [ebp+var_4]
.text:10001A9D push ecx
.text:10001A9E push eax
.text:10001A9F call sub_1000108B
.text:10001AA4 pop ecx
.text:10001AA5 test eax, eax
.text:10001AA7 pop ecx
.text:10001AA8 jz short loc_10001B12
.text:10001AAA xor eax, eax
.text:10001AAC cmp [ebp+var_4], edi
.text:10001AAF setz al
.text:10001AB2 cmp eax, ebx
.text:10001AB4
.text:10001AB4 loc_10001AB4: ; CODE XREF: sub_10001A39+5Fj
.text:10001AB4 jz short loc_10001B12
.text:10001AB6 mov [esi+4Ch], edi
.text:10001AB9 lea edi, [esi+54h]
.text:10001ABC push 14h
.text:10001ABE push edi
.text:10001ABF call sub_1000182D
.text:10001AC4 push edi ; char *
.text:10001AC5 call _strlen
.text:10001ACA add esp, 0Ch
.text:10001ACD lea ecx, [esi+180h]
.text:10001AD3 mov [esi+50h], ebx
.text:10001AD6 lea ebx, [esi+0B8h]
.text:10001ADC push ecx
.text:10001ADD push eax
.text:10001ADE push edi
.text:10001ADF push ebx
.text:10001AE0 push 101h
.text:10001AE5 mov [esi+184h], eax
.text:10001AEB push dword ptr [esi+2Ch]
.text:10001AEE call WkbCrypt2
.text:10001AF3 test eax, eax
.text:10001AF5 jge short loc_10001B10
.text:10001AF7 lea ecx, [ebp+var_4]
.text:10001AFA mov [esi+48h], eax
.text:10001AFD push ecx
.text:10001AFE push eax
.text:10001AFF call WkbIsComplete
.text:10001B04 test eax, eax
.text:10001B06 jz short loc_10001B16
.text:10001B08 and dword ptr [esi+48h], 0
.text:10001B0C cmp [ebp+var_4], 0
.text:10001B10
.text:10001B10 loc_10001B10: ; CODE XREF: sub_10001A39+BCj
.text:10001B10 jnz short loc_10001B25
.text:10001B12
.text:10001B12 loc_10001B12: ; CODE XREF: sub_10001A39+6Fj
.text:10001B12 ; sub_10001A39:loc_10001AB4j
.text:10001B12 xor eax, eax
.text:10001B14 jmp short loc_10001B42
.text:10001B16 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:10001B16
.text:10001B16 loc_10001B16: ; CODE XREF: sub_10001A39+CDj
.text:10001B16 call WkbGetLastError
...


I do not see any direkt calls except these 3.

I've used IDA's WinGraph32 to generate a calls view, I believe that's what you wanted?

Please use this link to d/l it :
hXXp://rapidshare.de/files/31300189/wkbcrypt2_graph.gdl.html

And this is a small (108 kb) dll that's communicating with WIBU:
hXXp://rapidshare.de/files/31301124/xxx.dll.html

Also, I have coded a fake dll (wkwin32.dll) with debugging feature (used with DebugView in combination) to help me in analyzing this. I'm still finishing the WkbCrypt2 debug function ...

Once again Sab, thank you for your help!

Waiting for your reply ;-)

fritzFS
August 30th, 2006, 10:25
I've finished with debug output in fake dll, so here goes the results:

Code:

00000000 0.00000000 [1340] [WIBU]: WkbGetVersion2(1)
00000001 0.00021763 [1340] [WIBU]: WkbQueryStatus2(1, 0, 12f01c, 4)
00000002 0.00113422 [1340] [WIBU]: WkbAccess2(200001, 12ef50)
00000003 0.00132866 [1340] [WIBU]: WkbOpen2(1, 101, 0, 72b, 3033, 0)
00000004 0.00151332 [1340] [WIBU]: WkbQuerySystem2(10, 1, 12efe8, 64)
00000005 0.00230588 [1340] [WIBU]: WkbSelect2(11, 110, 418, 15c878c)
00000006 0.00249473 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000007 0.00270146 [1340] [WIBU - WkbCrypt2 INPUT HEX]: A7 BA B2 96 81 87 F4 F4 F4 86 87 87 93 90 E3 CF C7 D2 DA DC 49 5A 5A 7C 05 0F 22 35 44 9D E6 F3 39 08 6C 32 C3 C3 BB 4C 55 C6 A0 E0 61 67 9A 66 13 BD D8 EC CF 73 01 C8
00000008 0.00296770 [1340] [WIBU]: WkbUnSelect2(11)
00000009 0.00313559 [1340] [WIBU]: WkbSelect2(11, 110, 828, 15c878c)
00000010 0.00333143 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000011 0.00349039 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 4B 56 5E D0 C7 C1 2C 2C 2C 93 9B 92 13 18 6F E9 E1 F4 6A 6C 8F 76 76 64 EB EB 40 C7 B2 4B CA DF 6F 90 F4 DE 45 45 16 9D 04 5C B6 D0 17 8B AA 6A F5 3B E8 6F 78 AC 13 06
00000012 0.00366024 [1340] [WIBU]: WkbUnSelect2(11)
00000013 0.00382199 [1340] [WIBU]: WkbSelect2(11, 110, 463, 15c878c)
00000014 0.00401168 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000015 0.00416924 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 83 9E 96 EC FB FD BC BC BC 5F 5F 5F 62 62 17 6D 65 70 4A 4C CB EE EE 95 B1 B2 01 21 56 C7 D2 C7 A3 80 E4 16 39 39 0A 11 3D 2A BA F0 F3 C3 8A E2 A9 47 08 2B 58 3C DF BC
00000016 0.00434078 [1340] [WIBU]: WkbUnSelect2(11)
00000017 0.00438240 [1340] [WIBU]: WkbSelect2(11, 110, 1f47, 15c878c)
00000018 0.00453493 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000019 0.00473328 [1340] [WIBU - WkbCrypt2 INPUT HEX]: DF C2 CA 22 35 33 04 04 04 35 34 31 F6 F6 8B C3 CB DE 3A 3C 05 32 32 A8 5B 5B E4 AD D8 89 CE DB CD 38 5C 0A 37 34 90 58 04 94 34 80 5D 9F FA FE 47 49 78 23 2D 80 B6 60
00000020 0.00499086 [1340] [WIBU]: WkbUnSelect2(11)
00000021 0.00515904 [1340] [WIBU]: WkbSelect2(11, 110, d7b, 15c878c)
00000022 0.00535627 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000023 0.00551886 [1340] [WIBU - WkbCrypt2 INPUT HEX]: F7 EA E2 CE D9 DF 54 54 54 0D 0D 0D 26 26 53 B7 BF AA 9A 9C 91 4A 4A 1C 35 35 A0 59 2C 95 F6 E3 B1 E8 8C E2 9B 9B AA 43 7C 24 A8 20 49 B7 5A D6 6B E5 18 31 88 D4 8D BA
00000024 0.00569039 [1340] [WIBU]: WkbUnSelect2(11)
00000025 0.00584823 [1340] [WIBU]: WkbSelect2(11, 110, 61a, 15c878c)
00000026 0.00603792 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000027 0.00620274 [1340] [WIBU - WkbCrypt2 INPUT HEX]: C7 DA D2 86 91 97 34 34 34 75 75 75 B6 B6 C3 9F 97 82 5A 5C 79 BA BA 3C 7D 7D 20 61 14 0D C6 D3 89 48 2C 92 D3 D3 9A DB 1C 04 30 60 D1 87 1A 86 23 AD 58 99 48 B4 F5 2A
00000028 0.00637148 [1340] [WIBU]: WkbUnSelect2(11)
00000029 0.00664638 [1340] [WIBU]: WkbSelect2(11, 110, 6e5, 15c878c)
00000030 0.00687518 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000031 0.00703888 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 7B 66 6E 98 8F 89 4C 4C 4C 28 29 2C 8C 82 FF 01 09 1C AA AC A7 06 06 42 26 26 C3 BA CA 53 FA EF 97 30 54 2E 8D 8D 26 86 67 75 AE 90 0F BB EA BA BD F3 A8 07 BA CC AB 94
00000032 0.00721265 [1340] [WIBU]: WkbUnSelect2(11)
00000033 0.00737300 [1340] [WIBU]: WkbSelect2(11, 110, 223a, 15c878c)
00000034 0.00770740 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000035 0.00786664 [1340] [WIBU - WkbCrypt2 INPUT HEX]: B3 AE A6 B4 A3 A5 DC DC DC D1 D2 D2 D1 D7 A7 85 8D 98 8A 8C E3 FE FE F2 8A 8A 83 9E EE CF C2 D7 2B 20 44 66 61 67 1B 1C 17 C9 B2 B0 EB F3 CA 32 51 1F C8 C3 98 5C 54 CC
00000036 0.00804935 [1340] [WIBU]: WkbUnSelect2(11)
00000037 0.00820747 [1340] [WIBU]: WkbSelect2(11, 110, 455, 15c878c)
00000038 0.00840526 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000039 0.00856561 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 7F 62 6A 92 85 83 44 44 44 21 21 21 9E 9E EB 13 1B 0E BA BC B5 12 12 6C C9 C9 E0 5D 28 B9 2E 3B DD 78 1C EA 47 47 F2 6F CC D4 C4 00 8D 3F 7A 1E D7 39 F8 55 A8 C4 A1 42
00000040 0.00873519 [1340] [WIBU]: WkbUnSelect2(11)
00000041 0.00889582 [1340] [WIBU]: WkbSelect2(11, 110, 116b, 15c878c)
00000042 0.00909222 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000043 0.00925369 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 0B 16 1E B0 A7 A1 AC AC AC 73 73 73 DA DA AF C9 C1 D4 6A 6C EF B6 B6 E4 4B 4B 40 27 52 EB 0A 1F CF 10 74 1E E5 E5 56 3D 84 DC D6 D0 37 4B AA 2A 15 9B E8 4F 78 2C F3 46
00000044 0.00929923 [1340] [WIBU]: WkbUnSelect2(11)
00000045 0.00946210 [1340] [WIBU]: WkbSelect2(11, 110, 1b59, 15c878c)
00000046 0.00962692 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000047 0.00990601 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 37 2A 22 EE F9 FF D4 D4 D4 2D 2D 2D 66 66 13 D7 DF CA 9A 9C 31 0A 0A 9C D5 D5 A0 F9 8C F5 B6 A3 51 68 0C A2 FB FB 6A A3 FC A4 88 20 29 F7 5A 16 4B 85 18 51 88 54 AD 7A
00000048 0.01008732 [1340] [WIBU]: WkbUnSelect2(11)
00000049 0.01024683 [1340] [WIBU]: WkbSelect2(11, 110, a34, 15c878c)
00000050 0.01044490 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000051 0.01060889 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 4B 56 5E 50 47 41 2C 2C 2C 13 13 13 1A 1A 6F 69 61 74 6A 6C 0F 76 76 64 6B 6B 40 47 32 CB CA DF EF 90 F4 DE C5 C5 16 1D 04 5C 36 D0 97 8B AA 6A 75 BB E8 EF 78 AC 93 06
00000052 0.01078321 [1340] [WIBU]: WkbUnSelect2(11)
00000053 0.01093910 [1340] [WIBU]: WkbSelect2(11, 110, 2209, 15c878c)
00000054 0.01114108 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000055 0.01130283 [1340] [WIBU - WkbCrypt2 INPUT HEX]: B7 AA A2 2E 39 3F D4 D4 D4 6D 6D 6D E6 E6 93 17 1F 0A 9A 9C 71 8A 8A 9C 15 15 A0 39 4C B5 36 23 91 68 0C 22 BB BB EA 63 FC A4 48 20 E9 77 5A 96 0B C5 18 91 88 54 ED FA
00000056 0.01147604 [1340] [WIBU]: WkbUnSelect2(11)
00000057 0.01163612 [1340] [WIBU]: WkbSelect2(11, 110, 59b, 15c878c)
00000058 0.01182972 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000059 0.01198979 [1340] [WIBU - WkbCrypt2 INPUT HEX]: FF E2 EA 52 45 43 44 44 44 E1 E1 E1 1E 1E 6B D3 DB CE BA BC 75 92 92 6C 89 89 E0 1D 68 F9 AE BB 9D 78 1C 6A 87 87 72 AF CD D6 04 00 CD BF 7A 9E 17 F9 F8 15 A8 C7 62 CB
00000060 0.01216328 [1340] [WIBU]: WkbUnSelect2(11)
00000061 0.01232307 [1340] [WIBU]: WkbSelect2(11, 110, 1469, 15c878c)
00000062 0.01236247 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef98, 12ef34, 38)
00000063 0.01254601 [1340] [WIBU - WkbCrypt2 INPUT HEX]: B7 AA A2 AE B9 BF D4 D4 D0 EC EF EA E5 E7 00 0A DB CE BA BC 75 92 92 6C 89 89 E0 1D 68 F9 AE BB 9D 78 1C 6A 87 87 72 AF CD D6 04 00 CD BF 7A 9E 17 F9 F8 15 A8 C7 62 CB
00000064 0.01271055 [1340] [WIBU]: WkbUnSelect2(11)
00000065 0.01355535 [1340] [WIBU]: WkbSelect2(11, 110, 223a, 15c878c)
00000066 0.01377074 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef08, 12ef6c, 38)
00000067 0.01393278 [1340] [WIBU - WkbCrypt2 INPUT HEX]: B3 AE A6 B4 A3 A5 DC DC DC D1 D2 D2 D1 D7 A7 85 8D 98 8A 8C E3 FE FE F2 8A 8A 83 9E EE CF C2 D7 2B 20 44 66 61 67 1B 1C 17 C9 B2 B0 EB F3 CA 32 51 1F C8 C3 98 5C 54 CC
00000068 0.01462281 [1340] [WIBU]: WkbUnSelect2(11)
00000069 0.01480104 [1340] [WIBU]: WkbSelect2(11, 110, 223a, 15c878c)
00000070 0.01500135 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef08, 12ef6c, 38)
00000071 0.01516170 [1340] [WIBU - WkbCrypt2 INPUT HEX]: B3 AE A6 B4 A3 A5 DC DC DC D1 D2 D2 D1 D7 A7 85 8D 98 8A 8C E3 FE FE F2 8A 8A 83 9E EE CF C2 D7 2B 20 44 66 61 67 1B 1C 17 C9 B2 B0 EB F3 CA 32 51 1F C8 C3 98 5C 54 CC
00000072 0.01584587 [1340] [WIBU]: WkbUnSelect2(11)
00000073 0.01602466 [1340] [WIBU]: WkbSelect2(11, 110, 223a, 15c878c)
00000074 0.01622525 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef08, 12ef6c, 38)
00000075 0.01638588 [1340] [WIBU - WkbCrypt2 INPUT HEX]: B3 AE A6 B4 A3 A5 DC DC DC D1 D2 D2 D1 D7 A7 85 8D 98 8A 8C E3 FE FE F2 8A 8A 83 9E EE CF C2 D7 2B 20 44 66 61 67 1B 1C 17 C9 B2 B0 EB F3 CA 32 51 1F C8 C3 98 5C 54 CC
00000076 0.01707116 [1340] [WIBU]: WkbUnSelect2(11)
00000077 0.01725527 [1340] [WIBU]: WkbSelect2(11, 110, 6e5, 15c878c)
00000078 0.01747401 [1340] [WIBU]: WkbCrypt2(11, 101, 12ef08, 12ef6c, 38)
00000079 0.01764191 [1340] [WIBU - WkbCrypt2 INPUT HEX]: 7B 66 6E 98 8F 89 4C 4C 4C 28 29 2C 8C 82 FF 01 09 1C AA AC A7 06 06 42 26 26 C3 BA CA 53 FA EF 97 30 54 2E 8D 8D 26 86 67 75 AE 90 0F BB EA BA BD F3 A8 07 BA CC AB 94
00000080 0.01798944 [1340] [WIBU]: WkbUnSelect2(11)
00000081 0.01816432 [1340] [WIBU]: WkbControlSystem2(10, 40030, 0, 0)
00000082 0.01832300 [1340] [WIBU]: WkbClose2(11)
00000083 0.09585213 [1340] [WIBU]: WkbRelease2(10)

FoxB
August 30th, 2006, 13:47
As i see - u log not full. u show only INPUT. OUTPUT is lost.

fritzFS
August 30th, 2006, 14:12
Hello,

yes, there is no output in my last post.
I don't think it's necessary and I published most of the output in my post before that post. Look at post with timestamp: 08-27-2006 07:21 PM.

Thanks to FoxB, I tried running sentinel monitor also and there's also traffic!

How can this be true when there's only one hardware?

I'll have to wait day or two to get my hands again on the dongle and try the monitor with dongle plugged in to see if there's response from the hardware ...

Also, I've updated my fake DLL so it outputs the data using OutputDebugString API and calls the original DLL and functions so I can monitor the calls and data with DebugView tool ...

fritzFS
September 4th, 2006, 08:43
Sab, are you there?

I haven't seen response for quite some time ... after the copy-paste and additional information ...
So, what do you think?

hope to see your reply soon

Sab
September 4th, 2006, 14:43
I forgot about the thread!

You have 3 major attacks.

I need to check the api ill get back to you but..

RNG Attack: The first is finding a flaw in rng that seeds wkbselect2. This is what differentiates the amount of seeds. So do you seen any problems below with this seeding?

.text:10001A3F xor ebx, ebx
.text:10001A41 push edi
.text:10001A42 push ebx ; time_t *
.text:10001A43 call _time
.text:10001A48 mov esi, [ebp+arg_0]
.text:10001A4B pop ecx
.text:10001A4C mov ecx, [ebp+arg_4]
.text:10001A4F push 1
.text:10001A51 and eax, 0FFFFh
.text:10001A56 pop edi
.text:10001A57 mov [esi+188h], eax

2. Wkbselect2/wkbcrypt2 Bugs: I am submitting a tutorial to arteam on this sometime this week, it will explain this. Basically if you seed these functions improperly you limit the amount of possible seeds. This is done by looking at the argument sent and if it is not seeding properly. See api guide for retun key length. I.e. if u do
push FF you get return keys of EFEFEFEF EFEFEFEF so 64bit key but truly only 255 possibilities. SO you can do generic emu. BUt if you seed correctly you should see push FFFFFFFF full 32bit capabilities , thats bad since u get true 64bit return keys. btw, max wibu dongle supports is 0xFFFFFFFFF so u in theory if u had enough space could do a 64bits * 0xFFFFFFFFF table. (ouch).

3. Your app LOOKS like it does a random seed which controls file open/save which is rare. But, wibu is flawed and can be generically emulated. myself, xor37, and deepz0ne made a solution about 6 years ago. These solutions are on the inet now for a couple hundred. These solutions are not related to me, i dont need petty cash from dongle emus. If neccesary we may start disclosing some details here for the fun of the app. Ill take a look at the arguments in ur list and figure out whats going on from it. Ill reply again once i see api guide again, im rusty as hell.

fritzFS
September 4th, 2006, 18:21
Welcome back Sab ;-)

Hmm ... question regarding 1st method:

Target is generating the seed (SelectionCode) with:
ulSelectCode = time(NULL) & 0xFFFF;

Can't we patch this call and hardcode some value in ulSelectCode or that would'nt help?

Ok, hope to see your reply soon ;-)

Sab
September 4th, 2006, 19:57
only if u want it to be incompatible with other people using the same application with a real dongle. Otherwise you can patch it to be just one query for all the save files. But when u open files created by other people, high probability it wont work. But i have to study the ruitine. I havent had time to look yet. I m working on a few other things at the moment. But remember if you patch the select code processs, how would you open a file that had a selectcode that was randomly generated by another user with at dongle? ( : Now im guessing they use that wkbcrypt to encrypt the file itself, otherwise if its not using the return values of the wkbselect to encrypt the file/open file u can just patch out all the calls easily and there is no problem in question, since they are random and unchecked and would leave u only with a table of calls that are static and remove the random ones, which i doubt is the case though. Ill let u know soon enough. Maybe someone else will answer as well. Btw, just at quick glance, correct me if I am wrong, but &ffff would leave you with only 0xFFFF possible seeds for wkbselect and you can just query 0-0xFFFF seeds to get all possible wkbselect2 seeds make a table, and use that to emulate wkbcrypt2 in indirect encryption mode. and viola your done too.

fritzFS
September 5th, 2006, 10:57
Ok, in that case ... patching is out of the picture ;-)

Btw, with that time(NULL) & 0xffff ... yes, something could be wrong since all examples in WIBU SDK has this:

Code:

// generate random Selection Code from system time
// use the seconds since January 1, 1970 and clear
// the three topmost bits because bit 29, 30 and 31
// have special meanings.
ulSC = ((ULONG)time(NULL)) & 0x0FFFFFFF;


In the meantime, I also hope that someone will jump in and comment something, but seems everyone is keeping the information secret :-(

Hmm, about that ... 0xFFFF possible seeds, generating a table and using that for emulation ... I would still need your help :-(

Thank you, hope to see your reply soon!

Sab
September 6th, 2006, 01:20
Looking at api guide i see...

------
Syntax

INT WkbSelect2(HWKBENTRY hwkbe, ULONG flCtrl, ULONG
ulSelectCode, VOID *pvCtrl)

wkbe contains the handle of an opened WIBU-BOX entry.
flCtrl contains flags which control the execution of the function. Following command codes are currently supported:

Command Meaning

WKB_SEL_DIRECT (0x0000) direct encryption/decryption via the WIBU-BOX
WKB_SEL_KNUTH20 (0x0010) indirect Knuth encrypt/decryption
WKB_SEL_DEC_FEAL (0x0020) indirect original FEAL decryption
WKB_SEL_ENC_FEAL (0x0030) indirect original FEAL encryption
WKB_SEL_DEC_PERM (0x0040) indirect permutation decryption.
WKB_SEL_ENC_PERM (0x0050) indirect permutation encryption.
WKB_SEL_SYMFEAL (0x0060) indirect symmetric FEAL encryption/decryption.

WKB_SEL_USE_CACHE (0x00F0) uses a previously set and cached indirect selection which was stored into the cache because the WKB_SEL_SET_CACHE was set in the WKBSELECT structure. The returned cache identification is stored in the ulSelectCode parameter instead of a Selection Code.

This parameter contains also standard function control flags.
ulSelectCode contains the Selection Code except the WKB_SEL_USE_CACHE option is set. If the WIBU-BOX entry was opened for WIBU-KEY, version 1, the code must be in range 0..65535. Otherwise the complete 32 bit range can be set. Bit 29, 30 and 31 are used for special purposes:

Flag Meaning

WKB_SC_BOXLIMIT (bit 31) reduces the Limit Counter of the entry by 1 if such a counter exists.
WKB_SC_NETLIMIT (bit 30) touches the user limitation in a WkNet or WkLAN subsystem. When this bit is set, the used entry may not be opened by WkbOpen2 and the WKB_OPEN_NONETLIMIT option set.

WKB_SC_EXPDATE (bit 29) checks the expiration date of the opened WIBU-BOX entry if it has such an added entry.

If the WIBU-BOX entry is opened with WkbOpen2 and the WKB_OPEN_FIND option, a Limit Counter or Expiration Date is only reduced or checked, if the first matched entry contains such an added entry. The use of WkbOpen2 with the WKB_OPEN_MULTIFIND option permits to open several WIBU-BOX entries at the same time and permits the touching of a Limit Counter or checking of an Expiration Date of any entry in the WIBU-BOX which match the specified Firm and User-Code including Master entries.

If the WKB_SEL_USE_CACHE option is set, this parameter contains the cache identification of a previously set selection.
pvCtrl points to optional control data for the selection. This parameter is used only for the selection of an indirect encryption or decryption and must be NULL for WKB_SEL_DIRECT or WKB_SEL_USE_CACHE. This data is stored in a WKBSELECT structure which must not be stored as a constant aggregate because some members are updated by the WkbSelect2 call.

------------
[1340] [WIBU]: WkbSelect2(11, 110, 418, 15c878c)
[1340] [WIBU]: WkbSelect2(11, 110, 828, 15c878c)
[1340] [WIBU]: WkbSelect2(11, 110, 463, 15c878c)

------------
I think what you have is the knuth20 implementation.
Because.. param 0x110 is..
WKB_SEL_KNUTH20 (0x0010) indirect Knuth encrypt/decryption
where as
0x120, 0x130 would be
WKB_SEL_DEC_FEAL (0x0020) indirect original FEAL decryption
WKB_SEL_ENC_FEAL (0x0030) indirect original FEAL encryption

------------
ulSelectCode: contains the Selection Code except the WKB_SEL_USE_CACHE option is set. If the WIBU-BOX entry was opened for WIBU-KEY, version 1, the code must be in range 0..65535. Otherwise the complete 32 bit range can be set. Bit 29, 30 and 31 are used for special purposes:
------------

Maybe just algo version 1 which is max 0xFFFF. So something like..
//PSUEDO EXAMPLE
//WkbSelect2

INT WKAPIENTRY _export WkbSelect2( HWKBENTRY hwkbe,
ULONG flCtrl,
ULONG ulSelectCode,
VOID FAR * pvCtrl )
{

/*
Line up uselectcode 0-0xFFFF and each address has Key. I forgot knuth20 keysize. I know feal is 64bit size. for feal scheduale.
*/

if( ( flCtrl) == WKB_SEL_KNUTH20)
{
Key = ArrayKey[ulSelectCode];

}

}

I am not 100% sure if its knuth, but judging by the argument passed (0x110) and the 0xFFFF seed, it probably is very likely. You can also decompile the wibu system dlls and find the knuth20 algo inside, and just forget the table idea. The knuth20 algo is super weak I forget its been a while but this might help..

void Algo_v1_Enc( DWORD dwSelectCode, BYTE * pInTable, BYTE * pOutTable )
{
asm {
mov ecx, dwSelectCode
mov esi, pInTable
mov ebp, pOutTable
xor eax, eax // reset eax content
mov edx, ecx // edx = dwSelectCode
mov al, ch // al = ( dwSelectCode & 0x0000FF00 ) >> 4
mov ecx, 0Bh // set counter for movsd
mov edi, ebp // edi points to pOutTable
repe movsd // move pInTable into pOutTable B * 4 bytes
movsw // move 2 more bytes
and eax, 0xFF // eax = ( dwSelectCode & 0x0000FF00 ) >> 4
and edx, 0xFF // edx = ( dwSelectCode & 0x000000FF )
mov cl, al // cl = al (see below)
movsb // mov 1 more byte
mov bl, [ebp+0] // bl = 1st pOutTable byte
add cl, dl // cl += dl
add bl, cl // bl += cl
mov esi, 1 // reset counter
mov [ebp+0], bl // stores in 1st pOutTable bl

loc_439CAB:
mov ecx, edx
add edx, edx
shr ecx, 7
and ecx, 1
mov bl, [esi+ebp]
or edx, ecx
mov ecx, eax
and ecx, 1
shl ecx, 7
shr eax, 1
or eax, ecx
mov cl, [esi+ebp-1]
add cl, al
add cl, dl
add bl, cl
mov [esi+ebp], bl
inc esi
cmp esi, 2Fh
jl short loc_439CAB
}
}

// -------------------------------------------------------------------------- //
void Algo_v1_Dec( DWORD dwSelectCode, BYTE * pInTable, BYTE * pOutTable )
{
asm {
mov ecx, dwSelectCode
mov esi, pInTable
push esi
mov ebp, pOutTable
xor eax, eax // reset eax content
mov edx, ecx // edx = dwSelectCode
mov al, ch // al = ( dwSelectCode & 0x0000FF00 ) >> 4
mov ecx, 0Bh // set counter for movsd
mov edi, ebp // edi points to pOutTable
repe movsd // move pInTable into pOutTable B * 4 bytes
movsw // move 2 more bytes
and eax, 0xFF // eax = ( dwSelectCode & 0x0000FF00 ) >> 4
and edx, 0xFF // edx = ( dwSelectCode & 0x000000FF )
mov cl, al // cl = al
movsb // mov 1 more byte
mov bl, [ebp+0] // bl = 1st pOutTable byte
add cl, dl // cl += dl
sub bl, cl // bl += cl
mov esi, 1 // reset counter
mov [ebp+0], bl // stores in 1st pOutTable bl
pop edi
loc_439CAB_:
mov ecx, edx
add edx, edx
shr ecx, 7
and ecx, 1
mov bl, [esi+ebp] //
or edx, ecx
mov ecx, eax
and ecx, 1
shl ecx, 7
shr eax, 1
or eax, ecx
mov cl, [esi+edi-1] // cl = Data[ Index ]
add cl, al // cl += AL
add cl, dl // cl += DL
sub bl, cl // bl -= ( Data[ Index - 1 ] cl + dl );
mov [esi+ebp], bl // Data[ Index ] = bl
inc esi
cmp esi, 2Fh
jl short loc_439CAB_
}
}

Search for those bytes and start tracing how it works. It looks like it uses indirect mode so only key is calculated inside dongle. Anyways im on glass 3 of wine so im going to stop typing cause i forgot already what i just typed. good luck.

fritzFS
September 6th, 2006, 08:06
Ok, I see.

I continued my analysis on WkbCrypt2 inside WKWIN32.DLL.

1)
Inside it, there is a switch that determinates which parameters will call a function _insideWKbCrypt2 (my name).

this is a list of parameters :
Code:

.text:20004EED jmp_here: ; CODE XREF: WkbCrypt2+1C9j
.text:20004EED mov edx, [esp+4+pcbDest] ; 0x12EE94 - ret num_of_enc_bytes
.text:20004EF1 push edx ; int
.text:20004EF2 mov edx, [esp+8+pvDest]
.text:20004EF6 push edi ; int
.text:20004EF7 push eax ; lp
.text:20004EF8 mov eax, [esp+10h+hwkbe]
.text:20004EFC push esi ; int
.text:20004EFD push ebx ; int
.text:20004EFE push eax ; int
.text:20004EFF push edx ; int
.text:20004F00 push ecx ; int
.text:20004F01 call insideWkbCrypt2_ => algorithm somewhere inside
.text:20004F06 call insideWkbCrypt2__
.text:20004F0B pop edi
.text:20004F0C pop esi
.text:20004F0D pop ebp
.text:20004F0E pop ebx
.text:20004F0F retn 18h


When we look inside fnc insideWkbCrypt2_ he have:

- start function
- call do_some_calculation_with_GetLocalTime()
- call IsBadReadPtr()
- call do_some_algo_1
- call do_some_algo_2
- call VirtualProtect
- call unknown_1 - too much functions inside to trace and analyze
- call VirtualProtect
- call GetCurrentProcess
- call FlushInstructionCache
- end function

When we look at do_some_algo_1 function:

Code:

.text:20003E90 do_some_algo_1 proc near ; CODE XREF: insideWkbCrypt2_+69p
.text:20003E90
.text:20003E90 arg_0 = dword ptr 4
.text:20003E90 arg_4 = dword ptr 8
.text:20003E90 arg_8 = dword ptr 0Ch
.text:20003E90
.text:20003E90 mov ecx, [esp+arg_4]
.text:20003E94 push esi
.text:20003E95 mov esi, [esp+4+arg_8]
.text:20003E99 xor eax, eax
.text:20003E9B push edi
.text:20003E9C mov edi, 8
.text:20003EA1 mov dl, [esi]
.text:20003EA3 inc esi
.text:20003EA4 test ecx, ecx
.text:20003EA6 jz short the_end
.text:20003EA8 push ebx
.text:20003EA9 push ebp
.text:20003EAA mov ebp, [esp+10h+arg_0]
.text:20003EAE mov [esp+10h+arg_8], ecx
.text:20003EB2
.text:20003EB2 loop_again: ; CODE XREF: do_some_algo_1+91j
.text:20003EB2 mov cl, dl
.text:20003EB4 and ecx, 1
.text:20003EB7 shr dl, 1
.text:20003EB9 dec edi
.text:20003EBA jnz short loc_20003EC4
.text:20003EBC mov dl, [esi]
.text:20003EBE mov edi, 8
.text:20003EC3 inc esi
.text:20003EC4
.text:20003EC4 loc_20003EC4: ; CODE XREF: do_some_algo_1+2Aj
.text:20003EC4 test ecx, ecx
.text:20003EC6 jz short loc_20003F17
.text:20003EC8 mov cl, [ebp+0]
.text:20003ECB mov byte ptr [esp+10h+arg_4], cl
.text:20003ECF mov ecx, [esp+10h+arg_4]
.text:20003ED3 and ecx, 0FFh
.text:20003ED9 mov ebx, ecx
.text:20003EDB xor ebx, eax
.text:20003EDD and ebx, 0Fh
.text:20003EE0 mov [esp+10h+arg_0], ebx
.text:20003EE4 mov ebx, eax
.text:20003EE6 mov eax, [esp+10h+arg_0]
.text:20003EEA shr ebx, 4
.text:20003EED mov eax, dword_2001703C[eax*4]
.text:20003EF4 and ebx, 0FFFh
.text:20003EFA xor eax, ebx
.text:20003EFC mov ebx, eax
.text:20003EFE shr ecx, 4
.text:20003F01 and ebx, 0Fh
.text:20003F04 xor ecx, ebx
.text:20003F06 shr eax, 4
.text:20003F09 mov ecx, dword_2001703C[ecx*4]
.text:20003F10 and eax, 0FFFh
.text:20003F15 xor eax, ecx
.text:20003F17
.text:20003F17 loc_20003F17: ; CODE XREF: do_some_algo_1+36j
.text:20003F17 mov ecx, [esp+10h+arg_8]
.text:20003F1B inc ebp
.text:20003F1C dec ecx
.text:20003F1D mov [esp+10h+arg_8], ecx
.text:20003F21 jnz short loop_again
.text:20003F23 pop ebp
.text:20003F24 pop ebx
.text:20003F25
.text:20003F25 the_end: ; CODE XREF: do_some_algo_1+16j
.text:20003F25 pop edi
.text:20003F26 pop esi
.text:20003F27 retn 0Ch
.text:20003F27 do_some_algo_1 endp


and when we look at do_some_algo_3 function:

Code:

.text:20003E20 arg_0 = dword ptr 8
.text:20003E20 arg_4 = dword ptr 0Ch
.text:20003E20
.text:20003E20 push esi
.text:20003E21 mov esi, [esp+arg_4]
.text:20003E25 xor eax, eax
.text:20003E27 test esi, esi
.text:20003E29 jz short loc_20003E7D
.text:20003E2B mov edx, [esp+arg_0]
.text:20003E2F push ebx
.text:20003E30 push edi
.text:20003E31
.text:20003E31 loc_20003E31: ; CODE XREF: do_some_algo_2+59j
.text:20003E31 mov cl, [edx]
.text:20003E33 mov ebx, eax
.text:20003E35 mov byte ptr [esp+8+arg_4], cl
.text:20003E39 mov ecx, [esp+8+arg_4]
.text:20003E3D and ecx, 0FFh
.text:20003E43 mov edi, ecx
.text:20003E45 xor edi, eax
.text:20003E47 and edi, 0Fh
.text:20003E4A shr ebx, 4
.text:20003E4D mov eax, dword_2001703C[edi*4]
.text:20003E54 and ebx, 0FFFh
.text:20003E5A xor eax, ebx
.text:20003E5C mov edi, eax
.text:20003E5E shr ecx, 4
.text:20003E61 and edi, 0Fh
.text:20003E64 xor ecx, edi
.text:20003E66 shr eax, 4
.text:20003E69 mov ecx, dword_2001703C[ecx*4]
.text:20003E70 and eax, 0FFFh
.text:20003E75 xor eax, ecx
.text:20003E77 inc edx
.text:20003E78 dec esi
.text:20003E79 jnz short loc_20003E31
.text:20003E7B pop edi
.text:20003E7C pop ebx
.text:20003E7D
.text:20003E7D loc_20003E7D: ; CODE XREF: do_some_algo_2+9j
.text:20003E7D pop esi
.text:20003E7E retn 8
.text:20003E7E do_some_algo_2 endp


do_some_algo_1 function seems like knuth20 algorithm? The number of arguments is same as in your posted code.

Unfortunatly, at this moment, I do not have access to dongle so I cannot confirm that those functions (do_some_algo_1 & do_some_algo_3) is used and trace it :-(

Ok, seems like a dead-point without the dongle now, right? I'll have to wait for dongle again.

2)
Sorry, but can you explain me that WkbSelect2 key generation? I thought that WkbSelect2 function only selects the algorithm (in our case, knuth20) and thats it. Also, the return values are TRUE and FALSE, no key there

3)
Btw, Sab, have you heard of WKBOXSIM.DLL and WKFIRM.DLL?
If I'm not wrong, this is a possible solution for WIBU targets:
- write a fake DLL (wkwin32.dll) which will redirect calls to WKBOXSIM.DLL insted of real WKWIN32.dll
- FSB is some kind of protection which ensures that no real FirmCode can be used with simulation (?) - patch the WKFIRM.DLL to ensure that it reads data correctly just like demo FirmCodes

The documentation says :

Code:

"On Developer’s Site, the WIBU-KEY COM Component searches for the
WKBOXSIM.DLL module, which simulates the complete Classic WIBUKEY
API of WKWIN32.DLL too, but supports also a lot of additional
features, which are available only for WIBU-KEY developers."

"The WKBOXSIM.DLL module uses – similar as WKCRYPT.EXE or
WKLIST32.EXE – the WKFIRM.DLL and the WKFIRM.WBC license file to
access the complete WIBU-BOX programming and WIBU-KEY Encryption
Algorithm simulation for all Firm Codes, which are stored in WKFIRM.WBC
and which are additionally protected (except Firm Code 10 up to 19) by the
FSB (Firm Security WIBU-BOX)."

"To use the Simulation Subsystem, WKBOXSIM.DLL and WKFIRM.DLL
must be installed and the BoxSim mode must be active (chapter 7.2.1, page
101).
/
Note
The Encryption Simulation Mode can simulate a WIBU-BOX for all
User Codes of a Firm Code or at least for a specific Firm Code and
User Code (in dependence of the contents of WKFIRM.WBC). But this
is no security lack or risk because the encryption behavior does not
depend on the COM Component or on the WKBOXSIM.DLL but on
the WKFIRM.WBC and the FSB and these two equipments are used in
a similar way by other tools like WKCRYPT.EXE, too."

Sab
September 6th, 2006, 12:38
u dont need dongle for this app. as far as wkboxsim/wkfirm, dont bother u would have to make a valid file encoding and still need to solve for the internal values anyways. U can definetly use it to study with and understand wkbselect. Bare in mind wkbselect selects the algo, but it also INITializes the algo too, before using wkbcrypt2. ig uses wait for dongle again.

fritzFS
September 9th, 2006, 11:48
Hello Sab,

I have found their knuth20 algorithm and it's pretty easy, but there are problems, of course ;-)

Code:

.text:2000F3F0 do_algo_3 proc near ; CODE XREF: do_algo_2+39p
.text:2000F3F0 ; do_algo_2+23Ep
.text:2000F3F0
.text:2000F3F0 arg_xxx = dword ptr 4 ==> KEY
.text:2000F3F0 arg_4 = dword ptr 8 ==> destination
.text:2000F3F0 arg_src = dword ptr 0Ch ==> encrypted data
.text:2000F3F0 arg_cbSrc = dword ptr 10h ==> num_of_bytes
.text:2000F3F0
.text:2000F3F0 mov ecx, [esp+arg_cbSrc] ; cbSrc
.text:2000F3F4 mov eax, [esp+arg_xxx] ; xxx
.text:2000F3F8 mov edx, ecx
.text:2000F3FA push esi ; 0
.text:2000F3FB mov esi, [eax+8] ; &xxx + 8 = 0x13
.text:2000F3FE dec ecx
.text:2000F3FF push edi
.text:2000F400 mov edi, [eax+0Ch] ; &xxx + 0c = 2
.text:2000F403 test edx, edx
.text:2000F405 jz short loc_2000F465
.text:2000F407 push ebx ; 0
.text:2000F408 mov ebx, [esp+0Ch+arg_4] ; pvDest
.text:2000F40C inc ecx
.text:2000F40D push ebp ; save pvCtrl
.text:2000F40E mov ebp, [esp+10h+arg_src] ; pvCtrl
.text:2000F412 mov [esp+10h+arg_xxx], ecx ; write 0x38 - cbSrc
.text:2000F416
.text:2000F416 loop_1: ; CODE XREF: do_algo_3+68j
.text:2000F416 mov cl, [eax+edi+18h] ; 0xF1, 0xE3 (2nd byte)
.text:2000F41A mov dl, [eax+esi+18h] ; 0xF1, 0xE3 (2nd time)
.text:2000F41E add dl, cl ; 0xE2
.text:2000F420 mov [eax+esi+18h], dl
.text:2000F424 mov cl, dl
.text:2000F426 xor edx, edx ; clear edx
.text:2000F428 and ecx, 0FFh ; 0xE2
.text:2000F42E mov dl, [ebp+0] ; dl = pvCtrl[ebp] - i.e. A7
.text:2000F431 xor edx, ecx ; 0x45 - this xor is our crypto function
.text:2000F433 inc ebp
.text:2000F434 test ebx, ebx ; ebp = pvDest
.text:2000F436 jz short end_of_pvDest ; no more bytes to decode?
.text:2000F438 mov [ebx], dl ; *pvDest = decrypted_byte ; i.e. 45
.text:2000F43A inc ebx ; increase pvDest ptr to next byte
.text:2000F43B
.text:2000F43B end_of_pvDest: ; CODE XREF: do_algo_3+46j
.text:2000F43B test esi, esi
.text:2000F43D jz short loc_2000F442
.text:2000F43F dec esi ; after = 0x12
.text:2000F440 jmp short taken_7 ; taken
.text:2000F442 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:2000F442
.text:2000F442 loc_2000F442: ; CODE XREF: do_algo_3+4Dj
.text:2000F442 mov esi, [eax+4]
.text:2000F445
.text:2000F445 taken_7: ; CODE XREF: do_algo_3+50j
.text:2000F445 test edi, edi ; 2
.text:2000F447 jz short loc_2000F44C
.text:2000F449 dec edi ; after = 1
.text:2000F44A jmp short taken_8 ; taken
.text:2000F44C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:2000F44C
.text:2000F44C loc_2000F44C: ; CODE XREF: do_algo_3+57j
.text:2000F44C mov edi, [eax+4]
.text:2000F44F
.text:2000F44F taken_8: ; CODE XREF: do_algo_3+5Aj
.text:2000F44F mov ecx, [esp+10h+arg_xxx] ; 0x38
.text:2000F453 dec ecx ; after = 0x37
.text:2000F454 mov [esp+10h+arg_xxx], ecx
.text:2000F458 jnz short loop_1 ; not last byte? ok, loop again
.text:2000F45A pop ebp
.text:2000F45B mov [eax+0Ch], edi
.text:2000F45E pop ebx
.text:2000F45F mov [eax+8], esi
.text:2000F462 pop edi
.text:2000F463 pop esi
.text:2000F464 retn


That's the decryption algorithm.

Only part we don't know how they are generated are key variables.
Somewhere inside WkbSelect2 we generate them:

7 examples of keys variables are this:

Code:

016E2168 xxx dd 10h ; DATA XREF: Stack[00000F64]:arg_0o
016E2168 ; Stack[00000F64]:arg_0o ...
016E216C dd 13h
016E2170 dd 13h
016E2174 dd 2
016E2178 dd 0BAADF00Dh ; ş║Ž
016E217C dd 0BAADF000h ; ş║Ž
016E2180 dd 0F1F1F1F1h ; ŻŻŻŻ
016E2184 dd 0F1F1F1F1h ; ŻŻŻŻ
016E2188 dd 0F1F1F1F1h ; ŻŻŻŻ
016E218C dd 0F1F1F1F1h ; ŻŻŻŻ
016E2190 dd 0F1F1F1F1h ; ŻŻŻŻ
016E2194 dd 0BAADF00Dh ; ş║Ž
016E2198 dd 0ABABABABh ; čččč
016E219C dd 0ABABABABh ; čččč

016E21B0 xxx dd 10h ; DATA XREF: Stack[00000F64]:arg_0o
016E21B0 ; Stack[00000F64]:arg_0o ...
016E21B4 dd 13h
016E21B8 dd 13h
016E21BC dd 2
016E21C0 dd 0BAADF00Dh ; ş║Ž
016E21C4 dd 0BAADF000h ; ş║Ž
016E21C8 dd 87878787h ; šššš
016E21CC dd 87878787h ; šššš
016E21D0 dd 87878787h ; šššš
016E21D4 dd 87878787h ; šššš
016E21D8 dd 87878787h ; šššš
016E21DC dd 0BAADF00Dh ; ş║Ž
016E21E0 dd 0ABABABABh ; čččč
016E21E4 dd 0ABABABABh ; čččč

016E21F8 unk_16E21F8 dd 10h ; DATA XREF: Stack[00000F64]:arg_0o
016E21F8 ; Stack[00000F64]:arg_0o ...
016E21FC dd 13h
016E2200 dd 13h
016E2204 dd 2
016E2208 dd 0BAADF00Dh ; ş║Ž
016E220C dd 0BAADF000h ; ş║Ž
016E2210 dd 0E3E3E3E3h ; ĐĐĐĐ
016E2214 dd 0E3E3E3E3h ; ĐĐĐĐ
016E2218 dd 0E3E3E3E3h ; ĐĐĐĐ
016E221C dd 0E3E3E3E3h ; ĐĐĐĐ
016E2220 dd 0E3E3E3E3h ; ĐĐĐĐ
016E2224 dd 0BAADF00Dh ; ş║Ž
016E2228 dd 0ABABABABh ; čččč
016E222C dd 0ABABABABh ; čččč

016E2168 xxx dd 10h ; DATA XREF: Stack[00000C94]:arg_0o
016E2168 ; Stack[00000C94]:arg_0o ...
016E216C dd 13h
016E2170 dd 13h
016E2174 dd 2
016E2178 dd 0BAADF00Dh ; ş║Ž
016E217C dd 0BAADF000h ; ş║Ž
016E2180 dd 0CDCDCDCDh ; ====
016E2184 dd 0CDCDCDCDh ; ====
016E2188 dd 0CDCDCDCDh ; ====
016E218C dd 0CDCDCDCDh ; ====
016E2190 dd 0CDCDCDCDh ; ====
016E2194 dd 0BAADF00Dh ; ş║Ž
016E2198 dd 0ABABABABh ; čččč
016E219C dd 0ABABABABh ; čččč

016E21F8 xxx dd 10h ; DATA XREF: Stack[00000C94]:arg_0o
016E21F8 ; Stack[00000C94]:arg_0o ...
016E21FC dd 13h
016E2200 dd 13h
016E2204 dd 2
016E2208 dd 0BAADF00Dh ; ş║Ž
016E220C dd 0BAADF000h ; ş║Ž
016E2210 dd 41414141h ; AAAA
016E2214 dd 41414141h ; AAAA
016E2218 dd 41414141h ; AAAA
016E221C dd 41414141h ; AAAA
016E2220 dd 41414141h ; AAAA
016E2224 dd 0BAADF00Dh ; ş║Ž
016E2228 dd 0ABABABABh ; čččč
016E222C dd 0ABABABABh ; čččč

016E2240 xxx dd 10h ; DATA XREF: Stack[00000C94]:arg_0o
016E2240 ; Stack[00000C94]:arg_0o ...
016E2244 dd 13h
016E2248 dd 13h
016E224C dd 2
016E2250 dd 0BAADF00Dh ; ş║Ž
016E2254 dd 0BAADF000h ; ş║Ž
016E2258 dd 9F9F9F9Fh ; ŔŔŔŔ
016E225C dd 9F9F9F9Fh ; ŔŔŔŔ
016E2260 dd 9F9F9F9Fh ; ŔŔŔŔ
016E2264 dd 9F9F9F9Fh ; ŔŔŔŔ
016E2268 dd 9F9F9F9Fh ; ŔŔŔŔ
016E226C dd 0BAADF00Dh ; ş║Ž
016E2270 dd 0ABABABABh ; čččč
016E2274 dd 0ABABABABh ; čččč

016E2240 xxx dd 10h ; DATA XREF: Stack[00000C94]:arg_0o
016E2240 ; Stack[00000C94]:arg_0o ...
016E2244 dd 13h
016E2248 dd 13h
016E224C dd 2
016E2250 dd 0BAADF00Dh ; ş║Ž
016E2254 dd 0BAADF000h ; ş║Ž
016E2258 dd 0FBFBFBFBh ; űűűű
016E225C dd 0FBFBFBFBh ; űűűű
016E2260 dd 0FBFBFBFBh ; űűűű
016E2264 dd 0FBFBFBFBh ; űűűű
016E2268 dd 0FBFBFBFBh ; űűűű
016E226C dd 0BAADF00Dh ; ş║Ž
016E2270 dd 0ABABABABh ; čččč
016E2274 dd 0ABABABABh ; čččč


So, as you said, WkbSelect2 generates that key variable and WkbCrypt2 just uses it? I tried tracing the WkbSelect2, but there's much much much code inside and little bit harder to trace everything :-(

Btw, the algorithm decrypt code in your last reply ... I see that you use just ulSelectCode, source and output data. That would be great if I could have function like that, but I do not understand your Data variable inside. What is that and how to retrieve it?

Thank you!

fritzFS
September 9th, 2006, 12:08
Additional information:

This is a same function in target (File->New) and the data is completly different every time.
I run it two times with my monitoring fake dll.

Anyway, this is just to confirm that table based emulation is pretty hard, except if generating somehow all (0xFFFF) the possible combinations.

Code:

# first time - File New
00000180 36.84647369 [2428] [WIBU]: WkbCrypt2(11, 101, 17a885c, 17a87f8, 14)
00000181 36.84666061 [2428] [WIBU - WkbCrypt2 INPUT HEX]: 50 51 51 4F 42 42 55 4A 4E 4B 46 42 58 47 46 48 4B 49 4F 53
00000182 36.84704208 [2428] [WIBU - ORIGINAL DEST]: BE BF BF AA A7 A7 89 96 92 98 95 91 92 8D 8C 89 8A 88 F7 EB

# second time - File New
00000180 58.59060287 [2972] [WIBU]: WkbCrypt2(11, 101, 17a882c, 17a87c8, 14)
00000181 58.59099197 [2972] [WIBU - WkbCrypt2 INPUT HEX]: 4D 57 5A 50 55 46 54 4C 51 4A 4E 43 43 50 49 4C 41 59 47 56
00000182 58.59117889 [2972] [WIBU - ORIGINAL DEST]: EB F1 FC 29 2C 3F 18 00 1D 55 51 5C B1 A2 BB 89 84 9C DF CE

fritzFS
September 9th, 2006, 17:19
WkbSelect2 & WkbCrypt2 implementation in targets functions (File New, File Open, ... ):


this is an a routine thats implements WIBU while the application is running:

Code:

.text:10001A39 sub_10001A39 proc near ; CODE XREF: sub_10001B47+60p
.text:10001A39
.text:10001A39 var_4 = dword ptr -4
.text:10001A39 arg_0 = dword ptr 8
.text:10001A39 arg_4 = dword ptr 0Ch
.text:10001A39
.text:10001A39 push ebp
.text:10001A3A mov ebp, esp
.text:10001A3C push ecx
.text:10001A3D push ebx
.text:10001A3E push esi
.text:10001A3F xor ebx, ebx
.text:10001A41 push edi
.text:10001A42 push ebx ; time_t *
.text:10001A43 call _time
.text:10001A48 mov esi, [ebp+arg_0]
.text:10001A4B pop ecx
.text:10001A4C mov ecx, [ebp+arg_4]
.text:10001A4F push 1
.text:10001A51 and eax, 0FFFFh
.text:10001A56 pop edi
.text:10001A57 mov [esi+188h], eax
.text:10001A5D cmp [ecx], edi
.text:10001A5F jnz short loc_10001A6E
.text:10001A61 or eax, 0A0000000h
.text:10001A66 mov [esi+188h], eax
.text:10001A6C mov [ecx], ebx
.text:10001A6E
.text:10001A6E loc_10001A6E: ; CODE XREF: sub_10001A39+26j
.text:10001A6E cmp [esi+14h], bx
.text:10001A72 lea ecx, [esi+8]
.text:10001A75 mov eax, 110h
.text:10001A7A mov [ecx], eax
.text:10001A7C jnz short loc_10001A86
.text:10001A7E and byte ptr [esi+16h], 0
.text:10001A82 mov [esi+14h], di
.text:10001A86
.text:10001A86 loc_10001A86: ; CODE XREF: sub_10001A39+43j
.text:10001A86 push ecx
.text:10001A87 push dword ptr [esi+188h]
.text:10001A8D push eax
.text:10001A8E push dword ptr [esi+2Ch]
.text:10001A91 call WkbSelect2
.text:10001A96 cmp eax, ebx
.text:10001A98 jge short loc_10001AB4
.text:10001A9A lea ecx, [ebp+var_4]
.text:10001A9D push ecx
.text:10001A9E push eax
.text:10001A9F call sub_1000108B
.text:10001AA4 pop ecx
.text:10001AA5 test eax, eax
.text:10001AA7 pop ecx
.text:10001AA8 jz short loc_10001B12
.text:10001AAA xor eax, eax
.text:10001AAC cmp [ebp+var_4], edi
.text:10001AAF setz al
.text:10001AB2 cmp eax, ebx
.text:10001AB4
.text:10001AB4 loc_10001AB4: ; CODE XREF: sub_10001A39+5Fj
.text:10001AB4 jz short loc_10001B12
.text:10001AB6 mov [esi+4Ch], edi
.text:10001AB9 lea edi, [esi+54h]
.text:10001ABC push 14h
.text:10001ABE push edi
.text:10001ABF call sub_1000182D
.text:10001AC4 push edi ; char *
.text:10001AC5 call _strlen
.text:10001ACA add esp, 0Ch
.text:10001ACD lea ecx, [esi+180h]
.text:10001AD3 mov [esi+50h], ebx
.text:10001AD6 lea ebx, [esi+0B8h]
.text:10001ADC push ecx
.text:10001ADD push eax
.text:10001ADE push edi
.text:10001ADF push ebx
.text:10001AE0 push 101h
.text:10001AE5 mov [esi+184h], eax
.text:10001AEB push dword ptr [esi+2Ch]
.text:10001AEE call WkbCrypt2
.text:10001AF3 test eax, eax
.text:10001AF5 jge short loc_10001B10
.text:10001AF7 lea ecx, [ebp+var_4]
.text:10001AFA mov [esi+48h], eax
.text:10001AFD push ecx
.text:10001AFE push eax
.text:10001AFF call WkbIsComplete
.text:10001B04 test eax, eax
.text:10001B06 jz short loc_10001B16
.text:10001B08 and dword ptr [esi+48h], 0
.text:10001B0C cmp [ebp+var_4], 0
.text:10001B10
.text:10001B10 loc_10001B10: ; CODE XREF: sub_10001A39+BCj
.text:10001B10 jnz short loc_10001B25
.text:10001B12
.text:10001B12 loc_10001B12: ; CODE XREF: sub_10001A39+6Fj
.text:10001B12 ; sub_10001A39:loc_10001AB4j
.text:10001B12 xor eax, eax
.text:10001B14 jmp short loc_10001B42
.text:10001B16 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:10001B16
.text:10001B16 loc_10001B16: ; CODE XREF: sub_10001A39+CDj
.text:10001B16 call WkbGetLastError
.text:10001B1B sub eax, 40h
.text:10001B1E neg eax
.text:10001B20 sbb eax, eax
.text:10001B22 inc eax
.text:10001B23 jmp short loc_10001B42
.text:10001B25 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:10001B25
.text:10001B25 loc_10001B25: ; CODE XREF: sub_10001A39:loc_10001B10j
.text:10001B25 lea eax, [esi+11Ch]
.text:10001B2B push eax
.text:10001B2C push dword ptr [esi+184h]
.text:10001B32 push ebx
.text:10001B33 push dword ptr [esi+188h]
.text:10001B39 push esi
.text:10001B3A call sub_10001985
.text:10001B3F add esp, 14h
.text:10001B42
.text:10001B42 loc_10001B42: ; CODE XREF: sub_10001A39+DBj
.text:10001B42 ; sub_10001A39+EAj
.text:10001B42 pop edi
.text:10001B43 pop esi
.text:10001B44 pop ebx
.text:10001B45 leave
.text:10001B46 retn
.text:10001B46 sub_10001A39 endp


It is same as before (as when apps loads), using knuth20 algorithm, but the seed is larger then 0xFFFF. They are using this:

ulSelectCode = time(NULL) & 0xFFFF | 0x0A0000000;

i.e. 0xa000f179

So unfortunatly, as you can see, if I have to generate table of responses (keys - wkbselect2), I would have to also generate for range 0xA0000000-0xA000FFFF.

One more thing ...
When the applications loads, first protected function(i.e. File New) that I run, it generates this 0xA000XXXX ulSelectCode and that ulSelectCode is used in every other protected function(i.e. File Open).

Sab
September 10th, 2006, 22:48
ulSelectCode = time(NULL) & 0xFFFF | 0x0A0000000;

is still length of 0xFFFF. It just starts with A, example..


10000000 - 1000FFFF still FFFF possibilities. As long as the Or 0x0A... is mandatory. When i get time i will take a look at your dll. You should be able to reverse the knuth algo key initliazation process with all the algos u already have though. And reconstruct the wkbselect process. and reconstruct wkbcrypt process.

fritzFS
September 11th, 2006, 02:36
About recovering the WkbSelect2 process ...

So, you're saying that it's possible to create those keys without WkbSelect2+DongleAttached? I thought that the dongle is (really) used when generating those keys. Btw, as I said, I started to trace that function, but it's not simple as knuth20 algorithm :-(

Sab
September 12th, 2006, 02:26
knuth20 as i said before was used for wkbcrypt2 i think. i.e. 0x110,0x130 example. wkbselect2 varies depending on algo being seeded. u will probably need dongle here. but i believe with current in outs u already have its possible to solve, however, u do not have the internal knowledge yet... try to get teh dongle again and do a dump of 0x0a000000-0x0a00FFFF for wkbselect2 and ur done. otherwise u got a task ahead of u, that i believe requires more programming/reversing knowledge then u have at this time. Although I think with some time you can solve it.

Fritz: will you be able to obtain the dongle again? If not i will start a new approach for you. but if you can get the dongle, then we can discuss making a dumper for when you get it back.

fritzFS
September 12th, 2006, 08:00
Hello Sab,

unfortunatly, I do not have access to dongle this moment, again.

I think I could access it, one more time ... I have to wait couple days for it and I'll have it max. 24 hours :-(

1)
I was also thinking about creating a dumper (program that uses WIBU...):

It should login in and do WkbSelect2 & WkbUnSelect2 X 0xFFFF times, with different SelectCode every time (of course).

The problem was with dumping the key data, I didn't see how could I do it since the key isn't written to argument passed by function or similiar, so I saw that as a dead-point (for me). I've took a look at disassembly knuth20 function and I traced it above ... traced where the key_structure is called, where is modified and where is used ...
Anyway, I found an variable (in wkwin32.dll) where this key_structure address is saved.

Code:

.data:2001759C ; DWORD NumberOfBytesRead
.data:2001759C NumberOfBytesRead dd 0 ; DATA XREF: sub_20001000+32r
.data:2001759C ; WkbRelease2+1Er ...
.data:200175A0 ; int Buffer
.data:200175A0 Buffer dd 0 ; DATA XREF: sub_20003D40+59r
.data:200175A0 ; sub_20003F30+27r ...
.data:200175A4 addr_xxx_structure dd 0 ; DATA XREF: sub_20003D40+15r
.data:200175A4 ; sub_20003F30r ...
.data:200175A8 aC19892000ByWib db '(C) 1989-2000 by WIBU-SYSTEMS',0
.data:200175C6 db 0Bh
.data:200175C7 db 48h ; H
.data:200175C8 db 1Dh
.data:200175C9 db 0Fh
.data:200175CA db 0EDh ; έ
.data:200175CB db 91h ; Ĺ


So, I was thinking ... could I do a dumper like this (since I never coded a dumper/unpacker)?

Code:

call WkbAccess2
call WkbOpen2
for (i = 0; i < 0xFFFF; i++) {
call WkbSelect2 // use 'i' as SelectCode
call ReadProcessMemory // use 0x200175A4 harcoded addr to get addr_xxx_address
call ReadProcessMemory // read whole key block (56 bytes)
call SQL_write_somewhere_selectcode_and_keyblock
call WkbUnSelect2
}

for(i = 0x0A000000; i < 0x0A00FFFF; i++) {
call WkbSelect2 // use 'i' as SelectCode
call ReadProcessMemory // use 0x200175A4 harcoded addr to get addr_xxx_address
call ReadProcessMemory // read whole key block (56 bytes)
call SQL_write_somewhere_selectcode_and_keyblock
call WkbUnSelect2
}
call WkbClose2


After that, I could just use SQL_read functions with simple syntax:
SELECT key WHERE selectcode = '_something_'
and use returned key in knuth20 algorithm that I've posted ;-)

Would this be a good way to do it?
Sorry, if bad, please do not start to flame ;-)

2)

Since I do not have an access to dongle and I would really like to solve it without it now, what can I do? :-(

Thank you, hope to hear from you soon!

Sab
September 12th, 2006, 14:48
Seems like you understand the concepts now. Yes, find the addr where the value is stored and just sniff it. Thats fine, you do need dongle for this. I dont know about the 0x0-0xFFFF, i didnt check if the and 0x0A is mandatory, if it is, then u just need 0x0A * 0xFFFF range. To do it without dongle, your going to have to figure out the wkbselect2 process for the knuth algo. It is very doable. Give it a try first, probably better you use a dongle OR, use the simulated file they have in the sdk, that acts just like the dongle, without a dongle present. Ahh, see i gave you a nice tip ( : go find wibu sdk.

fritzFS
September 12th, 2006, 15:01
Hello Sab,

just a note : I already have WIBU sdk from nice guy on #c4n ;-)

Use a simulated file (wkboxsim.dll and wkfirm.dll)? But you said that there's a protection around it and that has to be broken first ...

FoxB
September 13th, 2006, 01:23
Quote:
[Originally Posted by fritzFS]....Use a simulated file (wkboxsim.dll and wkfirm.dll)?...


U need have wkfirm.dat file for using this.

Sab
September 13th, 2006, 02:03
when i get time this weekend, I will find my old wibu stuff, as well as that thing you requested foxb. I think i can get u a file that allows simulation, although I recall it being in the sdk by deafult, but maybe im wrong, I can always modify the firm.dat i got a hold of and just strip it to the portion that allows simulation. There is no real reversing involved as far as obfuscation etc, its more along the lines of documenting and undrstanding hte process inside wkfirm and wkboxsim with the smiulated dongle file. So its just like if you had a peak inside a portion of the dongles asic logic. It doesnt show the entire process, but it does show enough.

fritzFS
September 18th, 2006, 11:49
Sab,

thank you for your help!

I have solved it.

There were about 25 fixed (static) ulSelectCode's, so I've calculated WkbCrypt2 keys for them.

The dynamic part of the ulSelectCode in the target, seems like it was only a additional security check. It generated random string and encrypted/decrypted it. I've patched the ulSelectCode parameter there to be fixed also and calculated key for it, added that in my fake DLL also so this check works now.

For now, the application is working fine. No unknown ulSelectCode's or anything yet. Seems to me that this is finished. I guess when I get the dongle again, I'll try to code and use a 0xffff dumper ....

Since I havent found too much documents about this, I have wrote something about my expirience, maybe someone will find it useful.

hXXp://rapidshare.de/files/33577548/wibu_analysis.pdf.html

Btw, do you know something about the wibu envelope?

Sab
September 18th, 2006, 13:53
Good Job Fritz. Glad to see you made something of hte posts, its rare that someone actually produces results. These types of things usually lead to a "okay i got it bye now!" Seems your skills upgrading just during this session, and hopefully helped others. Remember to double check that selectcode process and insure it is not indeed reliant on the fileopen/save, but if its just to check for presence, u are in good condition. Otherwise you are still in good condition as its only 0xffff. Yes i am familiar with wibu envelope, ill be posting some info on this thread later in the week regarding it. try doing some investigation on wkbcrypt.exe and encrypte some notepad.exes. Post what you find. Ill also be posting a pdf to arteam relatively soon. THis seems to be a very cool team and dedicated to quality / stability. So i will have it posted on this board once i finish it up.

uhabber
September 18th, 2006, 15:24
which version u try to crack..


4.1

5.0

5.1

fritzFS
September 18th, 2006, 15:35
All versions? ;-)

Isn't the algorithm the same?

Btw, currently I have WIBU SDK 4.0 :-(

I started to work on this envelope thingie ...

uhabber
September 18th, 2006, 15:42
i own versions 3.3 4.0 4.1 .4.11 5.0 5.1 SDK

and 2 Firm Codes of full Version with FSB
and one RU VERSION

my frimcodes.dat from 2 versions are open and does not use the FSB BOX
anyMORE ... hehe

on the RU VERSION NO SUCCESS ONLY WITH FSB.

fritzFS
September 18th, 2006, 15:53
uhabber,

can you help me with this function, I cannot find it's prototype in SDK ...

WkbDiagnose2

:-(

uhabber
September 18th, 2006, 15:58
func WkbDiagnose2 is not supported in the sdk

i have looked in the handbooks. form 3.3 above 5.1

nothing written down there 4 windows

fritzFS
September 18th, 2006, 16:02
yes, same problem here :-(

If you check export table of original WkWin32.DLL, you'll see WkbDiagnose2 with ordinal number 44 (0x2C). I'm missing this function in my fake DLL, I have to add it first so I can continue my work ;-)

I'll try to figure out something ...

uhabber
September 18th, 2006, 16:10
forgot the emulations dll.

wkcrypt supports the comunications dll inside the encrypted file

no wkwin32.dll will be called

wkcrypt version 5.0 and above

and the axp-crypt from codemeter supports the same (wibukey support included)

fritzFS
September 18th, 2006, 16:15
Yes, you are probably correct.

I have solved WkbDiagnose2 now, I've just set some dummy function and exported it, but there's another function _WkbProgramLow ... Anyway, I'm stopping this approach.

I tried to recode a fake DLL (WkWin32.DLL) for enveloped applications, but they use undocumented API's from WkWin32.DLL :-(
I wanted to forward those calls with my fake WkWin32.DLL to WkBoxSim.DLL, but it failes :-(

I tried protecting the notepad and analyzing it, but it fails since it cannot find the dongle :-(

Any advice?

uhabber
September 18th, 2006, 16:31
are u trying with firmcode 10

or personal firmcode

fritzFS
September 18th, 2006, 16:33
just for a test now ... firm 10

uhabber
September 18th, 2006, 16:33
i have stoped ... cracking wibu..

that is one of the best dongles in on earth.

ranks

1. megalock
2. wibu and hardlock eye
3. marx crypto box

uhabber
September 18th, 2006, 16:34
u need more then one code
u own a dongle

i can send u some programming stuff to u

fritzFS
September 19th, 2006, 07:51
I've used firmcode 10 in WkCrypt tool to encrypt small proggie ... but ...
Is there a way to sucessfully run the encrypted program?

It requires the dongle when I run it, which is logical, but still ... I also failed when I tried to forward those calls to WkBoxSim :-(

Anyone?

fritzFS
September 19th, 2006, 18:19
Sab,

these are my notes for the envelope:

[ During the protecting process with wkcrypt ]
- do protection (still unknown)
- rename all current PE section's names in .wkcryptP and .wkcryptE (name seems to depend on section itself - i.e. if .rsrc, call it .wkcryptP; if .text, call it .wkcryptE, etc ...)
- add these PE (wibu) sections on the end of file : .text, .rdata, .data, .CRT, reloc
- modify EP to point at .text

The protection uses AEEncryptFile function from wkautoenc.dll.
It's hard to track and figure out everything since there is too much calculations, unknown functions, etc ... :-(


- UNPACKING PROCESS -


WIBU code inside a target looks like:

Code:

.text:01014000 public start
.text:01014000 start proc near ; DATA XREF: start+Co
.text:01014000 test dword_1017424, 0FFh
.text:0101400A jnz short error_dont_match
.text:0101400C mov eax, offset start
.text:01014011 sub eax, EP
.text:01014017 mov EP, eax ; EP holds ImageBase now
.text:0101401C jmp short jump_taken
.text:0101401E ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:0101401E
.text:0101401E error_dont_match: ; CODE XREF: start+Aj
.text:0101401E pop eax
.text:0101401F pop ebx
.text:01014020 pop ecx
.text:01014021 mov dword_1017428, ecx
.text:01014027 push ecx
.text:01014028 push ebx
.text:01014029 push eax
.text:0101402A
.text:0101402A jump_taken: ; CODE XREF: start+1Cj
.text:0101402A call do_envelope
.text:0101402F mov eax, EP
.text:01014034 add eax, OEP
.text:0101403A jmp eax ; jump to our original entry point!
.text:0101403A start endp


Ok, when we take a look at do_envelope process we have this:

- call WkbGetVersion2() & WkbGetVersion3()
- call WkbAccess2()
- call unidentified_small_protection_algorithm X times
- while (Found_WkCryptE_WkbCryptP_Sections()) {
--- call VirtualProtect() - set READ_WRITE permissions
--- call WkbOpen2()
--- call WkbCrypt2() -> look below at disassembly A
--- call VirtualProtect() - return to original state - I guess
}

(WkbSelect2 is deprecated, so its not used)
Here goes the dissassembly A, that's how WkbCrypt2 looks like:

Code:

.text:01014C6C push ecx ; pcbDest
.text:01014C6D push ebx ; VSize - cbSrc
.text:01014C6E push edx ; 1 - pvCtrl
.text:01014C6F push eax ; VOffset - pvDest
.text:01014C70 push 102h ; flCtrl - WKB_STD_CTRL | WKB_CRYPT_BUFFER
.text:01014C75 push edi ; hwkbe
.text:01014C76 mov [esp+38h+var_14], 0
.text:01014C7E call WkbCrypt2


There is another WkbCrypt2 call with different parameters, but I cannot trace it yet. All I can say about that one, is that he's got different flCtrl parameter: 100h.

That is all I got so far.

fritzFS
September 20th, 2006, 18:50
Got it, thanks bye now!

---

Just kidding

Ok, I had access to WIBU dongle for this enveloped target and I sucessfully removed it. I have to say it was pretty easy. Of course, with the dongle.

I'll write something useful about it, but I have to go to sleep now ... expect some new notes soon!

Sab
September 21st, 2006, 18:59
Log the key values you used to unwrap it. Then go back and debug without dongle, and see if there are any openings, you should find.... Anyways post solution w/dongle. Itll be nice to add to this thread, when one day its cached/archived. Good work.

dELTA
September 30th, 2006, 07:32
So FritzFS, how about those notes?

FoxB
October 9th, 2006, 04:14
Quote:
[Originally Posted by fritzFS]...I had access to WIBU dongle for this enveloped target and I sucessfully removed it....



It is very easy. Try without

WBR

rf1911
October 9th, 2006, 08:48
I'd say that syncrosoft is the best dongle... anyone ever tried it?

Quote:
[Originally Posted by uhabber]i have stoped ... cracking wibu..

that is one of the best dongles in on earth.

ranks

1. megalock
2. wibu and hardlock eye
3. marx crypto box

5aLIVE
October 9th, 2006, 12:24
Quote:
[Originally Posted by dELTA]So FritzFS, how about those notes?


FritzFS posted them on the EXETools forum, I have attached them here for your reading pleasure.

Cheers.

Sab
October 9th, 2006, 13:10
syncrosoft is pretty good dongle. Reason it is difficult is it is undocumented first. Second is they hardcode the algorithm into the mcu and use it as a function. deepzone and a few others eventually got it down to a science, hence nuendo and cubase releases. For megalock, never even heard of it, but im betting at the market share and quanitity they distrobute at they probably use a very weak mcu and can be broken for a couple thousand (maybe). Wibu is a good solid dongle, with bad design and implementation security at its core. Hardlock is a piece of crap. Marx crypto is decent, but its cpu is pretty slow especially in rsa mode, so this would cause major latency issues in an application. Also they use a mcu that is crackable and have some holes laying around it. Your best dongles are always going to be the same now, a ready made fpga/secure controller with aes algorithm (secure dfrom side channel, power analysis etc) and a usb connected to it and voila you got yourself something that eats up anything in the past. Rockey should be mentioned here , but rockey is flawed as well, I mean honestly who can trust security chips made in China ( : Okay thats it. Also arteam will probably be release another tut on wibu im going to submit to them. Have a good one.

FoxB
October 9th, 2006, 13:20
Sab, u can tell name of the rockey4 hardware algo (des, rsa, aes, blowfish, idea)? if known.
user algo may be reversible, imho.

BWR

5aLIVE
October 9th, 2006, 13:28
Quote:
[Originally Posted by Sab] Also arteam will probably be release another tut on wibu im going to submit to them. Have a good one.


Hi Sab,
I was going to ask you about this in my previous post as I enjoyed follwing this thread with great interest. I'm no dongle buster myself, but I always enjoy reading on how resourceful individuals such as yourself circumvent these devices. Any idea when we can expect to see your paper?

PS. Can you elaborate a little on what you mean by "secured from side channel, power analysis" as I'm not famaliar these terms. Thanks.

Rgds,
5aLIVE.

pacraf
October 10th, 2006, 11:17
@5aLive:
any piece of hardware (dongle, smart card , etc) can be analyzed not only from "software" side , but or/also from hardware side. Nowadays most of them are better secured, but earlier there were some possibilities to "unlock - whatever that means" its content.
For example - power analysis - if u know hardware architecture , u can precicely watch power consumption of microcontroler used in dongle. by determining momentary power consumption you are able to say if there in somenthing written in sram , ond so on (i am not familiar with this - so maybe i am wrong)
there are several others way to analyse hardware - microprobing , lowering power supply voltage for several microseconds (for ustable operations)

Sab
October 10th, 2006, 14:45
Well, if you want to know about hardware reversing, that is a very very technical, and limit access field. I would say a great place to start is probably one of the most comphrensive phd essays ive read Cambridge Univeritsy, its by Sergei (forgot his last name), very smart. Also includes some insight on the hasp4 dongle. here you go.. 11.8mb

http://www.cl.cam.ac.uk/TechReports/UCAM-CL-TR-630.pdf

That should cover all your topics quite nicely. Have fun. Dont private msg me about hw hacking btw, i dont know , if u want u can find info and prices on websites through google, or some universities have great equipment and ta's/professors that are down for the cause ( :

fritzFS
October 18th, 2006, 12:43
Hello guys,

thank you for your replys.

(Un)fortunatly my college started and I ain't got much free time anymore :-(

I wanted to describe the WIBU Envelope unpacking process and try to unpack it without the dongle, but I guess I have to postpone that... :-(

Anyway, here are quick notes (with dongle):

- in previous post's on this thread I marked the OEP location in enveloped apps
- set a BP on that location and run the app
- after that, step one instruction forward to get to the OEP
- run your favorite dumper (LordPE, ProcDump, OllyDump, ...) and dump process with your new new OEP
- now there's only Import Table to fix.
- run ImpRec on your running application to get the import table
- get those imports, there shouldnt be any unresolved!
- save those results with FixDump button in ImpRec into dumped exe

- voilla, that's all

Thank you for your help Sab

dELTA
October 18th, 2006, 15:39
Better late than never, thanks for the info.

FoxB
October 19th, 2006, 00:33
Additional research for USB token.

WBR

formater
February 19th, 2009, 12:35
hi fritzFS,
You wrote 3 years ago:

"I wanted to describe the WIBU Envelope unpacking process and try to unpack it without the dongle, but I guess I have to postpone that... :-("

Any news about that? I have some target, but no access to dongle

Regards,
Formater

FoxB
February 19th, 2009, 12:47
@formater: the wibu shell not have full info for unpacking it without dongle

formater
February 21st, 2009, 03:23
Tnx FoxB the quick answer
That's too bad, if it's not possible, because I see, that if there is dongle, finding the OEP is pretty easy

FoxB
February 21st, 2009, 09:07
@formater: no joy without the dongdle/emulator and with OEP

ps: can show your FirmCode/UserCode for the target?

formater
February 21st, 2009, 09:40
If i'm correctly reading this code:
Code:

.text:0098BF2D mov eax, dword_98E028
.text:0098BF32 mov ecx, dword_98E024
.text:0098BF38 mov edx, dword_98E000
.text:0098BF3E push 0
.text:0098BF40 push eax <------ usercode
.text:0098BF41 mov eax, [esi]
.text:0098BF43 push ecx <------ firmcode
.text:0098BF44 or edx, 120h
.text:0098BF4A push 0
.text:0098BF4C push edx
.text:0098BF4D push eax
.text:0098BF4E call WkbOpen


Then
usercode: 000003E8
firmcode: 0003D1A1

Regards,
Formater

FoxB
February 21st, 2009, 10:29
no dump - no help