Check out the new blog at http://linuxehacking.ovh , this one will no longer be updated

domenica 20 luglio 2014

Alcor UFD Controller Hacking update 2

In these days between some exercises for a microeconomics exam , i've continued to work on reverse engineering the Alcor 698x UFD microcontroller, and i've got another poor quality Alcor based flash drive from a friend , so now i've an 8 GB one , and a 4 GB one.

I've started , with the help of wireshark , usbmon and a virtual machine running windows with USB forwarding by SPICE , reverse engineering the format of the various vendor specific commands that are sent to the flash drive.

But while working on it i've encountered a serious problem , the Linux kernel scsi implementation removes the 3 MSBs from the 2nd byte of the SCSI commands , which in our case , breaks various commands , for example , 0x51 directed at LUN 0 , would become 0x11.

The interesting commands now are two: 0x82 and 0x81 , they are used to download and upload configurations to the flash drive.


The 0x81 command is used with that specific CDB



0x81 , 0x00 0xff , 0x00 , 0x00 , 0x00 , 0x00, 0x00 ,0x00 ,0x00 ,0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 

Then it takes 512 bytes of data that contains the actual configuration, below there's an example of that configuration:


Let's look at what i've found so far:
Going from the start of the file to the end

99 07 : This seems to be some sort of signature i have yet to find a flash drive that does not have it
10 : This is the vendor string length ( including zeroes , the length field itself and the type field )
26: This is the product string length ( including zeroes , the length field itself and the type field )
12 01 10 01 00 00 00 08: These bytes are still unknown , 12 could be the SCSI vendor string length , but still not tested
8F 05: This is the little endian representation of the VID ( Vendor ID ) that the usb device will show to the PC
87 63: This is the little endian representation of the PID ( Product ID ) that the usb device will show to the computer
05 01: These are the bcdDevice field of the usb descriptor
01:  Manufacter index ( not confirmed )
02: Product index , ( not confirmed )
00 01: Unknown
10: Again vendor string length
03: Descriptor type ( String)
10 03 48 00 61 00 63 00 6B 00 69 00 6E 00 67 00: Actual Vendor String
26: Product string length ( Again )
03: Descriptor type ( String )
50 00 52 00 4F 00 56 00 41 00 50 00 52 00 4F 00 44 00 4F 00 54 00 54 00 4F 00 50 00 52 00 4F 00 56 00 41 00: The actual product string
47 65 6E 65 72 69 63 20 46 6C 61 73 68 20 44 69 73 6B 20 20 20 20 20 20 38 2E 30 30: SCSI Identification string (Generic Flash Disk      8.00)
02: This byte is a checksum of the all bytes before it , if you set it incorrectly , the flash drive will refuse to use the settings, to calculate it , sum all bytes values ( unsigned ) , and then do &0xFF to use only the first eight bits.
AA 55 : Unknown 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : Padding
3C C3 : Unknown
2A : Serial string length
03: Descriptor type (String )
32 00 30 00 31 00 34 00 30 00 37 00 31 00 39 00 31 00 34 00 31 00 34 00 32 00 37 00 30 00 38 00 35 00 46 00 30 00 37 00 42: The actual serial number string

After that there are @ offset 0xc3 an 0xc7 two 02 which are unknown
And @ 0xd4 there's 88 50 51 49 which is unknown too

Once the settings have been uploaded , the flash drive has to be unplugged and plugged in again

The 0x82 command

This command instead, is used to read current configuration, it can be used in two ways

82 51 01 00 00 00 00 00 00 00

In that way you will get the current usb configuration with the same format as 0x81 command, 512 bytes too

82 51 00 00 00 00 00 00 00 00 

With this one instead you get another configuration(maybe) that still has to be investigated, and i have to figure out how it is uploaded too


I've created a git repository on github.com containing the kernel patch and the current code for the alcorhack tool


Again , if someone wants to help, contact me on G+ or comment here 

sabato 12 luglio 2014

Alcor UFD Controller Reverse engineering part 1 , querying info and decrypting the flash list shipped in AlcorMP tool

I've started that work because i want to port AlcorMP utility to Linux and to be able to use custom flash chips with these UFD chips, this utility called AlcorMP allows to do a lot of stuff , from checking flash integrity to programming the usb flash drive into a CD-Rom emulator.

For who is new to that field, these flash drives store configuration data and badblocks on an hidden sector of the flash memowy which normally is not visible by the end user.

To program that sector you have to issue vendor specific SCSI commands, the ones that i've found are:
0x9a: Seems to return 0x200 bytes of data still not reverse engineered
0xfa00: Seems to return 0x200 bytes of data too, but this one returns the Flash Chip identification as the first 6 bytes , so it's something useful.
There's also 0xf5 that is still unknown

Now the hard part, first thing you will see when you try to figure out where the program takes the flash part.no and vendor, is that there's no plaintext list with that data, and there's no compressed data either.
Analyzing it with binwalk gives a very discouraging entropy graph as shown below
flashlist.afl entropy plot using binwalk -E


After some work on the UfdComLib.dll , it turns out that the file flashlist.afl has been encrypted with a block cipher on purpose.

Lucky the program itself ( except LLF.dll that is encrypted too ), is not obfuscated , so it has been relatively easy extracting the encryption algorithm from the program and use it to decode the flashlist.afl .

The function on UfdComLib.dll that gives an huge help locating the decryption code with IDA is the one at 0x100022F0

.text:100022F0 .text:100022F0 ; =============== S U B R O U T I N E ======================================= .text:100022F0 .text:100022F0 ; Attributes: bp-based frame .text:100022F0 .text:100022F0 ; int __cdecl sub_100022F0(LPCSTR lpFileName) .text:100022F0 sub_100022F0 proc near ; CODE XREF: sub_10001D80+292p .text:100022F0 .text:100022F0 ReturnedString = byte ptr -14Ch .text:100022F0 var_44 = byte ptr -44h .text:100022F0 var_40 = byte ptr -40h .text:100022F0 var_3C = byte ptr -3Ch .text:100022F0 var_38 = byte ptr -38h .text:100022F0 var_36 = byte ptr -36h .text:100022F0 var_34 = byte ptr -34h .text:100022F0 var_32 = byte ptr -32h .text:100022F0 var_30 = byte ptr -30h .text:100022F0 var_2E = byte ptr -2Eh .text:100022F0 AppName = byte ptr -2Ch .text:100022F0 var_24 = dword ptr -24h .text:100022F0 var_20 = dword ptr -20h .text:100022F0 var_1C = dword ptr -1Ch .text:100022F0 var_18 = dword ptr -18h .text:100022F0 var_14 = dword ptr -14h .text:100022F0 var_10 = dword ptr -10h .text:100022F0 var_C = dword ptr -0Ch .text:100022F0 var_4 = dword ptr -4 .text:100022F0 hFile = dword ptr 8 .text:100022F0 .text:100022F0 push ebp .text:100022F1 mov ebp, esp .text:100022F3 push 0FFFFFFFFh .text:100022F5 push offset SEH_100022F0 .text:100022FA mov eax, large fs:0 .text:10002300 push eax .text:10002301 mov large fs:0, esp .text:10002308 sub esp, 140h .text:1000230E push ebx .text:1000230F push esi .text:10002310 push edi .text:10002311 mov edi, [ebp+hFile] .text:10002314 xor esi, esi .text:10002316 mov [ebp+var_10], esp .text:10002319 push esi ; hTemplateFile .text:1000231A push 80h ; dwFlagsAndAttributes .text:1000231F push 3 ; dwCreationDisposition .text:10002321 push esi ; lpSecurityAttributes .text:10002322 push 1 ; dwShareMode .text:10002324 push 80000000h ; dwDesiredAccess .text:10002329 push edi ; lpFileName .text:1000232A mov [ebp+var_14], esi .text:1000232D mov [ebp+var_4], esi .text:10002330 call ds:CreateFileA .text:10002336 cmp eax, 0FFFFFFFFh .text:10002339 jz short loc_10002371 .text:1000233B push eax ; hObject .text:1000233C call ds:CloseHandle .text:10002342 push 4 ; int .text:10002344 push edi ; lpFileName .text:10002345 call sub_10004220 .text:1000234A mov ebx, eax .text:1000234C add esp, 8 .text:1000234F cmp ebx, esi .text:10002351 mov [ebp+var_24], ebx .text:10002354 ja short loc_100023BD .text:10002356 push offset aError_flash_it ; "ERROR_FLASH_ITEM_COUNT" .text:1000235B lea ecx, [ebp+var_40] .text:1000235E call ??0CString@@QAE@PBD@Z ; CString::CString(char const *) .text:10002363 lea eax, [ebp+var_40] .text:10002366 push offset unk_10006950 .text:1000236B push eax .text:1000236C call _CxxThrowException .text:10002371 ; --------------------------------------------------------------------------- .text:10002371 .text:10002371 loc_10002371: ; CODE XREF: sub_100022F0+49j .text:10002371 push offset asc_100081E4 ; "\r\n" .text:10002376 lea ecx, [ebp+hFile] .text:10002379 call ??0CString@@QAE@PBD@Z ; CString::CString(char const *) .text:1000237E mov esi, eax .text:10002380 push offset aError_file_no_ ; "ERROR_FILE_NO_EXISTS: " .text:10002385 lea ecx, [ebp+var_24] .text:10002388 mov byte ptr [ebp+var_4], 1 .text:1000238C call ??0CString@@QAE@PBD@Z ; CString::CString(char const *) .text:10002391 push edi .text:10002392 push eax .text:10002393 lea eax, [ebp+var_18] .text:10002396 mov byte ptr [ebp+var_4], 2 .text:1000239A push eax .text:1000239B call ??H@YG?AVCString@@ABV0@PBD@Z ; operator+(CString const &,char const *) .text:100023A0 push esi .text:100023A1 lea ecx, [ebp+var_3C] .text:100023A4 push eax .text:100023A5 push ecx .text:100023A6 mov byte ptr [ebp+var_4], 3 .text:100023AA call ??H@YG?AVCString@@ABV0@0@Z ; operator+(CString const &,CString const &) .text:100023AF lea edx, [ebp+var_3C] .text:100023B2 push offset unk_10006950 .text:100023B7 push edx .text:100023B8 call _CxxThrowException .text:100023BD ; --------------------------------------------------------------------------- .text:100023BD .text:100023BD loc_100023BD: ; CODE XREF: sub_100022F0+64j .text:100023BD mov eax, ebx .text:100023BF shl eax, 5 .text:100023C2 add eax, ebx .text:100023C4 lea ecx, [eax+eax*4] .text:100023C7 lea edx, [ebx+ecx*2] .text:100023CA shl edx, 1 .text:100023CC push edx ; unsigned int .text:100023CD call ??2@YAPAXI@Z ; operator new(uint) .text:100023D2 add esp, 4 .text:100023D5 cmp eax, esi .text:100023D7 mov [ebp+var_18], eax .text:100023DA jz short loc_1000240A .text:100023DC mov [ebp+var_14], ebx .text:100023DF mov esi, 296h .text:100023E4 mov edx, eax .text:100023E6 .text:100023E6 loc_100023E6: ; CODE XREF: sub_100022F0+114j .text:100023E6 mov ecx, [ebp+var_14] .text:100023E9 dec ecx .text:100023EA mov [ebp+var_14], ecx .text:100023ED js short loc_10002406 .text:100023EF mov ecx, 0A5h .text:100023F4 xor eax, eax .text:100023F6 mov edi, edx .text:100023F8 add edx, esi .text:100023FA rep stosd .text:100023FC stosw .text:100023FE mov edi, [ebp+hFile] .text:10002401 mov eax, [ebp+var_18] .text:10002404 jmp short loc_100023E6 .text:10002406 ; --------------------------------------------------------------------------- .text:10002406 .text:10002406 loc_10002406: ; CODE XREF: sub_100022F0+FDj .text:10002406 xor esi, esi .text:10002408 jmp short loc_1000240C .text:1000240A ; --------------------------------------------------------------------------- .text:1000240A .text:1000240A loc_1000240A: ; CODE XREF: sub_100022F0+EAj .text:1000240A xor eax, eax .text:1000240C .text:1000240C loc_1000240C: ; CODE XREF: sub_100022F0+118j .text:1000240C push ebx ; int .text:1000240D push esi ; int .text:1000240E push eax ; int .text:1000240F push 4 ; int .text:10002411 push edi ; hFile .text:10002412 mov [ebp+var_14], eax .text:10002415 call sub_100043D0 .text:1000241A add esp, 14h .text:1000241D cmp eax, esi .text:1000241F jnz short loc_1000243C .text:10002421 push offset aError_flashlis ; "ERROR_FlashListApi_ReadItem\r\n" .text:10002426 lea ecx, [ebp+var_44] .text:10002429 call ??0CString@@QAE@PBD@Z ; CString::CString(char const *) .text:1000242E lea eax, [ebp+var_44] .text:10002431 push offset unk_10006950 .text:10002436 push eax .text:10002437 call _CxxThrowException .text:1000243C ; --------------------------------------------------------------------------- .text:1000243C .text:1000243C loc_1000243C: ; CODE XREF: sub_100022F0+12Fj .text:1000243C push 0FFFFFFFFh .text:1000243E push esi .text:1000243F mov ecx, offset unk_10008430 .text:10002444 call sub_10003060 .text:10002449 cmp ebx, esi .text:1000244B jnz short loc_1000249E .text:1000244D mov edi, dword_10008434 .text:10002453 cmp edi, esi .text:10002455 jz short loc_1000248D .text:10002457 mov esi, dword_10008438 .text:1000245D .text:1000245D loc_1000245D: ; CODE XREF: sub_100022F0+180j .text:1000245D mov ecx, esi .text:1000245F dec esi .text:10002460 test ecx, ecx .text:10002462 jz short loc_10002472 .text:10002464 push 0 ; char .text:10002466 mov ecx, edi ; void * .text:10002468 call sub_100040E0 .text:1000246D add edi, 10h .text:10002470 jmp short loc_1000245D .text:10002472 ; --------------------------------------------------------------------------- .text:10002472 .text:10002472 loc_10002472: ; CODE XREF: sub_100022F0+172j .text:10002472 mov edx, dword_10008434 .text:10002478 push edx ; void * .text:10002479 call ??3@YAXPAX@Z ; operator delete(void *) .text:1000247E add esp, 4 .text:10002481 mov dword_10008434, 0 .text:1000248B xor esi, esi .text:1000248D .text:1000248D loc_1000248D: ; CODE XREF: sub_100022F0+165j .text:1000248D mov dword_1000843C, esi .text:10002493 mov dword_10008438, esi .text:10002499 jmp loc_100025C7 .text:1000249E ; --------------------------------------------------------------------------- .text:1000249E .text:1000249E loc_1000249E: ; CODE XREF: sub_100022F0+15Bj .text:1000249E mov edx, dword_10008434 .text:100024A4 cmp edx, esi .text:100024A6 jnz short loc_100024D3 .text:100024A8 mov eax, ebx .text:100024AA shl eax, 4 .text:100024AD push eax ; unsigned int .text:100024AE call ??2@YAPAXI@Z ; operator new(uint) .text:100024B3 add esp, 4 .text:100024B6 mov dword_10008434, eax .text:100024BB push ebx .text:100024BC push eax .text:100024BD call sub_10003DF0 .text:100024C2 mov dword_1000843C, ebx .text:100024C8 .text:100024C8 loc_100024C8: ; CODE XREF: sub_100022F0:loc_10002501j .text:100024C8 ; sub_100022F0+223j .text:100024C8 mov dword_10008438, ebx .text:100024CE jmp loc_100025C7 .text:100024D3 ; --------------------------------------------------------------------------- .text:100024D3 .text:100024D3 loc_100024D3: ; CODE XREF: sub_100022F0+1B6j .text:100024D3 mov ecx, dword_1000843C .text:100024D9 cmp ebx, ecx .text:100024DB jg short loc_10002523 .text:100024DD mov eax, dword_10008438 .text:100024E2 cmp eax, ebx .text:100024E4 jge short loc_10002501 .text:100024E6 mov ecx, ebx .text:100024E8 sub ecx, eax .text:100024EA shl eax, 4 .text:100024ED add eax, edx .text:100024EF push ecx .text:100024F0 push eax .text:100024F1 call sub_10003DF0 .text:100024F6 mov dword_10008438, ebx .text:100024FC jmp loc_100025C7


This function uses another function to read the header and get the number of entries on the flash list file , sub_10004220

.text:10004220 .text:10004220 ; =============== S U B R O U T I N E ======================================= .text:10004220 .text:10004220 .text:10004220 ; int __cdecl sub_10004220(LPCSTR lpFileName, int) .text:10004220 sub_10004220 proc near ; CODE XREF: sub_100022F0+55p .text:10004220 .text:10004220 var_100 = dword ptr -100h .text:10004220 var_DC = dword ptr -0DCh .text:10004220 var_D4 = dword ptr -0D4h .text:10004220 lpFileName = dword ptr 4 .text:10004220 arg_4 = dword ptr 8 .text:10004220 .text:10004220 mov ecx, [esp+lpFileName] .text:10004224 sub esp, 100h .text:1000422A lea eax, [esp+100h+var_100] .text:1000422E push esi .text:1000422F push eax ; int .text:10004230 push ecx ; lpFileName .text:10004231 xor esi, esi .text:10004233 call sub_10004270 .text:10004238 add esp, 8 .text:1000423B test eax, eax .text:1000423D jnz short loc_10004247 .text:1000423F pop esi .text:10004240 add esp, 100h .text:10004246 retn .text:10004247 ; --------------------------------------------------------------------------- .text:10004247 .text:10004247 loc_10004247: ; CODE XREF: sub_10004220+1Dj .text:10004247 mov edx, [esp+104h+var_DC]

This one above checks if the file has been read successfully and if yes, it returns the number of entries of the flash list file.

.text:10004270 .text:10004270 ; =============== S U B R O U T I N E ======================================= .text:10004270 .text:10004270 ; Attributes: bp-based frame .text:10004270 .text:10004270 ; int __cdecl sub_10004270(LPCSTR lpFileName, int) .text:10004270 sub_10004270 proc near ; CODE XREF: sub_10004220+13p .text:10004270 .text:10004270 Buffer = byte ptr -328h .text:10004270 var_228 = byte ptr -228h .text:10004270 var_128 = byte ptr -128h .text:10004270 dwErrCode = dword ptr -28h .text:10004270 NumberOfBytesRead= dword ptr -24h .text:10004270 var_20 = dword ptr -20h .text:10004270 var_1C = dword ptr -1Ch .text:10004270 var_18 = dword ptr -18h .text:10004270 var_14 = dword ptr -14h .text:10004270 var_10 = dword ptr -10h .text:10004270 var_C = dword ptr -0Ch .text:10004270 var_4 = dword ptr -4 .text:10004270 lpFileName = dword ptr 8 .text:10004270 arg_4 = dword ptr 0Ch .text:10004270 .text:10004270 push ebp .text:10004271 mov ebp, esp .text:10004273 push 0FFFFFFFFh .text:10004275 push offset SEH_10004270 .text:1000427A mov eax, large fs:0 .text:10004280 push eax .text:10004281 mov large fs:0, esp .text:10004288 sub esp, 31Ch .text:1000428E push ebx .text:1000428F push esi .text:10004290 mov eax, [ebp+lpFileName] .text:10004293 push edi .text:10004294 xor esi, esi .text:10004296 mov [ebp+var_10], esp .text:10004299 push esi ; hTemplateFile .text:1000429A push 80h ; dwFlagsAndAttributes .text:1000429F mov edi, 1 .text:100042A4 push 3 ; dwCreationDisposition .text:100042A6 push esi ; lpSecurityAttributes .text:100042A7 push edi ; dwShareMode .text:100042A8 push 80000000h ; dwDesiredAccess .text:100042AD push eax ; lpFileName .text:100042AE mov [ebp+var_14], edi .text:100042B1 mov [ebp+var_4], esi .text:100042B4 call ds:CreateFileA .text:100042BA mov ebx, eax .text:100042BC cmp ebx, 0FFFFFFFFh .text:100042BF mov [ebp+lpFileName], ebx .text:100042C2 jnz short loc_100042D5 .text:100042C4 lea ecx, [ebp+var_20] .text:100042C7 push offset unk_100069F0 .text:100042CC push ecx .text:100042CD mov [ebp+var_20], esi .text:100042D0 call _CxxThrowException .text:100042D5 ; --------------------------------------------------------------------------- .text:100042D5 .text:100042D5 loc_100042D5: ; CODE XREF: sub_10004270+52j .text:100042D5 lea edx, [ebp+NumberOfBytesRead] .text:100042D8 push esi ; lpOverlapped .text:100042D9 push edx ; lpNumberOfBytesRead .text:100042DA lea eax, [ebp+Buffer] .text:100042E0 push 200h ; nNumberOfBytesToRead .text:100042E5 push eax ; lpBuffer .text:100042E6 push ebx ; hFile .text:100042E7 call ds:ReadFile .text:100042ED cmp [ebp+NumberOfBytesRead], 200h .text:100042F4 jz short loc_10004307 .text:100042F6 lea ecx, [ebp+var_18] .text:100042F9 push offset unk_100069F0 .text:100042FE push ecx .text:100042FF mov [ebp+var_18], edi .text:10004302 call _CxxThrowException .text:10004307 ; --------------------------------------------------------------------------- .text:10004307 .text:10004307 loc_10004307: ; CODE XREF: sub_10004270+84j .text:10004307 lea edx, [ebp+var_128] .text:1000430D lea eax, [ebp+Buffer] .text:10004313 push edx .text:10004314 push 10h .text:10004316 push offset unk_10006840 .text:1000431B push 100h .text:10004320 push eax .text:10004321 call sub_10004650 .text:10004326 mov esi, [ebp+arg_4] .text:10004329 add esp, 14h .text:1000432C lea ecx, [ebp+var_128] .text:10004332 lea edx, [ebp+var_228] .text:10004338 push esi .text:10004339 push 100h .text:1000433E push ecx .text:1000433F push 100h .text:10004344 push edx .text:10004345 call sub_10004650 .text:1000434A add esp, 14h .text:1000434D mov ecx, 4 .text:10004352 mov edi, offset unk_10006840 .text:10004357 xor eax, eax .text:10004359 repe cmpsd .text:1000435B jz short loc_100043A4 .text:1000435D lea ecx, [ebp+var_1C] .text:10004360 push offset unk_100069F0 .text:10004365 push ecx .text:10004366 mov [ebp+var_1C], 2 .text:1000436D call _CxxThrowException .text:10004372 ; --------------------------------------------------------------------------- .text:10004372 .text:10004372 loc_10004372: ; DATA XREF: .rdata:stru_10006E88o .text:10004372 mov edx, [ebp+dwErrCode] .text:10004375 mov [ebp+var_14], 0 .text:1000437C push edx ; dwErrCode .text:1000437D call ds:SetLastError .text:10004383 mov eax, offset loc_100043A1 .text:10004388 retn .text:10004389 ; --------------------------------------------------------------------------- .text:10004389 .text:10004389 loc_10004389: ; DATA XREF: .rdata:stru_10006E88o .text:10004389 push 0FFh ; dwErrCode .text:1000438E mov [ebp+var_14], 0 .text:10004395 call ds:SetLastError .text:1000439B mov eax, offset loc_100043A1 .text:100043A0 retn .text:100043A1 ; --------------------------------------------------------------------------- .text:100043A1 .text:100043A1 loc_100043A1: ; DATA XREF: sub_10004270+113o .text:100043A1 ; sub_10004270+12Bo .text:100043A1 mov ebx, [ebp+lpFileName] .text:100043A4 .text:100043A4 loc_100043A4: ; CODE XREF: sub_10004270+EBj .text:100043A4 cmp ebx, 0FFFFFFFFh .text:100043A7 jz short loc_100043B0 .text:100043A9 push ebx ; hObject .text:100043AA call ds:CloseHandle .text:100043B0 .text:100043B0 loc_100043B0: ; CODE XREF: sub_10004270+137j .text:100043B0 mov ecx, [ebp+var_C] .text:100043B3 mov eax, [ebp+var_14] .text:100043B6 pop edi .text:100043B7 pop esi .text:100043B8 mov large fs:0, ecx .text:100043BF pop ebx .text:100043C0 mov esp, ebp .text:100043C2 pop ebp .text:100043C3 retn .text:100043C3 sub_10004270 endp ; sp-analysis failed .text:100043C3 .text:100043C3 ; ---------------------------------------------------------------------------


sub_10004270 is interesting, it actually opens the file and reads a 512 byte block, then a function is used multiple times on the data read from the file: sub_10004650

sub_10004650 is just a wrapper around sub_10004680 , and it does only dereference some char ** to char* , so let's checkout sub_10004680


.text:10004680 .text:10004680 ; =============== S U B R O U T I N E ======================================= .text:10004680 .text:10004680 .text:10004680 ; int __cdecl sub_10004680(char *, int, char *, int, char *) .text:10004680 sub_10004680 proc near ; CODE XREF: sub_10004650+19p .text:10004680 .text:10004680 arg_0 = dword ptr 4 .text:10004680 arg_4 = dword ptr 8 .text:10004680 arg_8 = dword ptr 0Ch .text:10004680 arg_C = dword ptr 10h .text:10004680 arg_10 = dword ptr 14h .text:10004680 .text:10004680 push ebx .text:10004681 push ebp .text:10004682 mov ebp, [esp+8+arg_0] .text:10004686 push edi .text:10004687 test ebp, ebp .text:10004689 jz loc_10004750 .text:1000468F mov ebx, [esp+0Ch+arg_8] .text:10004693 test ebx, ebx .text:10004695 jz loc_10004750 .text:1000469B mov edi, [esp+0Ch+arg_10] .text:1000469F test edi, edi .text:100046A1 jz loc_10004750 .text:100046A7 push esi .text:100046A8 push 100h ; unsigned int .text:100046AD call ??2@YAPAXI@Z ; operator new(uint) .text:100046B2 mov esi, eax .text:100046B4 mov eax, [esp+14h+arg_C] .text:100046B8 push esi .text:100046B9 push eax .text:100046BA push ebx .text:100046BB call sub_10004760 .text:100046C0 mov edx, [esp+20h+arg_4] .text:100046C4 add esp, 10h .text:100046C7 xor eax, eax .text:100046C9 xor ecx, ecx .text:100046CB test edx, edx .text:100046CD jbe short loc_10004740 .text:100046CF sub ebp, edi .text:100046D1 mov [esp+10h+arg_0], edx .text:100046D5 .text:100046D5 loc_100046D5: ; CODE XREF: sub_10004680+BAj .text:100046D5 inc eax .text:100046D6 and eax, 0FFh .text:100046DB mov dl, [eax+esi] .text:100046DE mov bl, [eax+esi] .text:100046E1 add edx, ecx .text:100046E3 and edx, 0FFh .text:100046E9 mov ecx, edx .text:100046EB mov dl, [ecx+esi] .text:100046EE xor bl, dl .text:100046F0 mov [eax+esi], bl .text:100046F3 mov dl, bl .text:100046F5 mov bl, [ecx+esi] .text:100046F8 xor bl, dl .text:100046FA mov [ecx+esi], bl .text:100046FD mov dl, bl .text:100046FF mov bl, [eax+esi] .text:10004702 xor bl, dl .text:10004704 mov [eax+esi], bl .text:10004707 mov dl, bl .text:10004709 xor ebx, ebx .text:1000470B and edx, 0FFh .text:10004711 mov bl, [ecx+esi] .text:10004714 add edx, ebx .text:10004716 and edx, 800000FFh .text:1000471C jns short loc_10004726 .text:1000471E dec edx .text:1000471F or edx, 0FFFFFF00h .text:10004725 inc edx .text:10004726 .text:10004726 loc_10004726: ; CODE XREF: sub_10004680+9Cj .text:10004726 mov dl, [edx+esi] .text:10004729 mov bl, [edi+ebp] .text:1000472C xor dl, bl .text:1000472E mov [edi], dl .text:10004730 mov edx, [esp+10h+arg_0] .text:10004734 inc edi .text:10004735 dec edx .text:10004736 mov [esp+10h+arg_0], edx .text:1000473A jnz short loc_100046D5 .text:1000473C mov edi, [esp+10h+arg_10] .text:10004740 .text:10004740 loc_10004740: ; CODE XREF: sub_10004680+4Dj .text:10004740 push esi ; void * .text:10004741 call ??3@YAXPAX@Z ; operator delete(void *) .text:10004746 add esp, 4 .text:10004749 mov eax, edi .text:1000474B pop esi .text:1000474C pop edi .text:1000474D pop ebp .text:1000474E pop ebx .text:1000474F retn .text:10004750 ; --------------------------------------------------------------------------- .text:10004750 .text:10004750 loc_10004750: ; CODE XREF: sub_10004680+9j .text:10004750 ; sub_10004680+15j ... .text:10004750 pop edi .text:10004751 pop ebp .text:10004752 xor eax, eax .text:10004754 pop ebx .text:10004755 retn .text:10004755 sub_10004680 endp .text:10004755 .text:10004755 ; ---------------------------------------------------------------------------

This one is clearly an encryption algorithm, but before having a complete view on the problem there's also another function: sub_10004760
s
.text:10004760 .text:10004760 ; =============== S U B R O U T I N E ======================================= .text:10004760 .text:10004760 .text:10004760 sub_10004760 proc near ; CODE XREF: sub_10004680+3Bp .text:10004760 .text:10004760 arg_0 = dword ptr 4 .text:10004760 arg_4 = dword ptr 8 .text:10004760 arg_8 = dword ptr 0Ch .text:10004760 .text:10004760 push ebx .text:10004761 mov ebx, [esp+4+arg_0] .text:10004765 test ebx, ebx .text:10004767 jz short loc_100047CC .text:10004769 mov ecx, [esp+4+arg_8] .text:1000476D test ecx, ecx .text:1000476F jz short loc_100047CC .text:10004771 push ebp .text:10004772 push esi .text:10004773 push edi .text:10004774 xor edi, edi .text:10004776 xor eax, eax .text:10004778 .text:10004778 loc_10004778: ; CODE XREF: sub_10004760+21j .text:10004778 mov [eax+ecx], al .text:1000477B inc eax .text:1000477C cmp eax, 100h .text:10004781 jb short loc_10004778 .text:10004783 mov ebp, [esp+10h+arg_4] .text:10004787 xor esi, esi .text:10004789 .text:10004789 loc_10004789: ; CODE XREF: sub_10004760+63j .text:10004789 mov eax, esi .text:1000478B xor edx, edx .text:1000478D div ebp .text:1000478F mov al, [edx+ebx] .text:10004792 mov dl, [esi+ecx] .text:10004795 add edi, edx .text:10004797 add eax, edi .text:10004799 and eax, 0FFh .text:1000479E mov edi, eax .text:100047A0 mov al, [edi+ecx] .text:100047A3 xor dl, al .text:100047A5 mov [esi+ecx], dl .text:100047A8 mov al, dl .text:100047AA mov dl, [edi+ecx] .text:100047AD xor dl, al .text:100047AF mov [edi+ecx], dl .text:100047B2 mov al, dl .text:100047B4 mov dl, [esi+ecx] .text:100047B7 xor dl, al .text:100047B9 mov [esi+ecx], dl .text:100047BC inc esi .text:100047BD cmp esi, 100h .text:100047C3 jb short loc_10004789 .text:100047C5 pop edi .text:100047C6 pop esi .text:100047C7 pop ebp .text:100047C8 mov eax, ecx .text:100047CA pop ebx .text:100047CB retn


After studying on it some hours i've figured out that sub_10004760 is a function used to inizialize a vector of length 256 ( 0x100 ) with the encryption key that is later used on the caller function.
With HexRays decompiler it's fairly easy to generate proper C code of these functions and so re-use them.

The file is made of a first 256 byte block , that encrypted using the algorithm above and "ALCORFLASHCFG_SZ" as the key yields other 256 bytes that have to be used as the key for the next 256 byte block inside the file that is the header.

The header contains some useful info like the size of each record , the number of records and what i think to be the version ( 4 ) as follows:

typedef struct {
  char headerMagic[16];
  int unk1;
  int unk2;
  int unk3;
  int unk4;
  int unk5; // 1
  int version; //Confirmed?
  int entry_size; // Confirmed?
  int entry_count;
    
} AlcorFlashListHeader;

The data after the header is organized in entry_size sized blocks and each one is decrypted using the same key obtained to decrypt the header, but , the first keybyte has to be the record number starting from 0 and the last keybyte has to be the bitwise negation of the record number

This gives us records on which i'm still working to figure out the exact format , but what i've defined so far:
typedef struct {
  unsigned char vendor[16];
  unsigned char partno[32];
  unsigned char id[6];
  unsigned char unk1[0xb];
  unsigned char CE;
....

Other fields still have to be reverse engineered, and they are mandatory to be able to write a program that can reprogram these flash drives.

The complete program that can read the flash list is the following:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LOBYTE(v) *((unsigned char*)&v)

#pragma pack(push, 1)
typedef struct {
  char headerMagic[16];
  int unk1;
  int unk2;
  int unk3;
  int unk4;
  int unk5; // 1
  int version; //Confirmed?
  int entry_size; // Confirmed?
  int entry_count;
    
} AlcorFlashListHeader;
typedef struct {
  unsigned char vendor[16];
  unsigned char partno[32];
  unsigned char id[6];
  unsigned char unk1[0xb];
  unsigned char CE;
  /*unsigned char unk2[14];
  unsigned char cache_enabled;*/
  unsigned char unk[0x260-(1+0xb)];
} AlcorFlashListEntry;
#pragma pack(pop)
// It seems to be some kind of block cipher using 0x100 ( 256 bytes) blocks
unsigned char * init_Vector(const unsigned char * enc_key , int keylen, unsigned char * out)
{
    int v4;
    unsigned int v3;
    unsigned int v5;
    unsigned int v6;
    unsigned int v7;

    unsigned char * res = NULL;
    if ( enc_key && out )
    {
        v4 = 0;
        v3 = 0;
        do {
            out[v3] = v3;
            ++v3;

        } while ( v3 < 0x100 );
        v5 = 0;
        do
        {
            v6 = v5 / keylen;
            v7 = v5 % keylen;
            LOBYTE(v6) = enc_key[v5 % keylen];
            LOBYTE(v7) = out[v5];
            v4 = (v7 + v4 + v6) & 0xFF;
            LOBYTE(v7) = out[v4] ^ v7;
            out[v5] = v7;
            LOBYTE(v7) = v7 ^ out[v4];
            out[v4] = v7;
            out[v5++] ^= v7;


        } while ( v5 < 0x100 );
        res = out;
    } else {
        res = 0;
    }
    return res;
}
void * decryptBlock(unsigned char * buffer, int bufferlen, const unsigned char * enc_key, int keylen, unsigned char * output)
{
    unsigned char * v5; // edi@3
    int v6; // eax@4
    int v7; // edx@4
    int v8; // ecx@4
    unsigned char *v9; // esi@4
    int v10; // ebp@5
    unsigned char v11; // bl@6
    unsigned char v12; // bl@6
    unsigned char v13; // bl@6
    unsigned char* result; // eax@8
    int v16; // [sp+10h] [bp+4h]@5

    if ( buffer && enc_key && ( v5 = output, output ))
    {
        v9 = new unsigned char[0x100];
        init_Vector(enc_key, keylen, v9);
        v7 = bufferlen;
        v6 = 0;
        v8 = 0;
        if ( bufferlen )
        {
            v10 = buffer - output;
            v16 = bufferlen;
            do
            {
                v6 = (v6 + 1) & 0xFF;
                LOBYTE(v7) = v9[v6];
                v8 = (v8 + v7) & 0xFF;
                v11 = v9[v8] ^ v9[v6];
                v9[v6] = v11;
                v12 = v11 ^ v9[v8];
                v9[v8] = v12;
                v13 = v12 ^ v9[v6];
                v9[v6] = v13;
                *v5 = v5[v10] ^ v9[(v9[v8] + v13) % 256];
                ++v5;
                v7 = v16 - 1;
            }
            while ( v16-- != 1 );
            v5 = output;
        }
        delete[] v9;
        result = v5;

    }
}
int main(int argc, char **argv) {
    FILE * f = fopen(argv[1],"rb");
    unsigned char buffer[512];
    fread(buffer,512,1,f);
    unsigned char out1[256];
    decryptBlock(buffer,256,(const unsigned char*)"ALCORFLASHCFG_SZ",16,out1);
    unsigned char out2[512];
    decryptBlock(&buffer[256],256,out1,256,out2);
    
   // fwrite(out2,256,1,stdout);
    AlcorFlashListHeader hdr;
    memcpy(&hdr,out2,sizeof(hdr));
    printf("File version: %d\n",hdr.version);
    printf("Entry size: %d\n",hdr.entry_size);
    printf("Entry count: %d\n",hdr.entry_count);
    
    unsigned char * completebuffer = new unsigned char[std::min(1024*1024*128, hdr.entry_size*hdr.entry_count)];
    unsigned char * completebuffer_enc = new unsigned char[std::min(1024*1024*128, hdr.entry_size*hdr.entry_count)];
    memset(completebuffer,0,hdr.entry_size*hdr.entry_count);
    
    int nb = fread(completebuffer_enc,1,hdr.entry_count*hdr.entry_size,f);
    if ( nb != hdr.entry_count*hdr.entry_size )
        abort();
    for ( int i = 0; i < hdr.entry_count; i++ )
    {
        out1[0] = i;
        out1[255] = ~(i + (unsigned char)0 /*a4*/);
        decryptBlock(&completebuffer_enc[hdr.entry_size*i],hdr.entry_size,out1,256,&completebuffer[hdr.entry_size*i]);
    }
    //fwrite(completebuffer,1,hdr.entry_size*hdr.entry_count,stdout);
    
    AlcorFlashListEntry * entries = (AlcorFlashListEntry*)completebuffer;
    for ( int i = 0; i < hdr.entry_count; i++ )
    {
        printf("%s - %s , ID: %02x%02x%02x%02x%02x%02x ",entries[i].vendor,entries[i].partno,entries[i].id[0],entries[i].id[1],entries[i].id[2],entries[i].id[3],entries[i].id[4],entries[i].id[5]);
     /*   if ( !entries[i].cache_enabled )
        {
            printf("-No cache enabled-");
        }*/
        
        printf(" CE = %d, ADD Data:",entries[i].CE);
        for ( int k = 0; k < 32; k++ )
        {
            printf("%02x",entries[i].unk1[k]);
            
        }
        printf("\n");
    }
    
    return 0;
}

If someone is interested in helping me on that work , comment here, or circle me on Google Plus