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

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:

1

2

3

4

5

6

7

8

9

10

11

12

<b>typedef</b><b>struct</b>{

charheaderMagic[16];

intunk1;

intunk2;

intunk3;

intunk4;

intunk5;// 1

intversion;//Confirmed?

intentry_size;// Confirmed?

intentry_count;

}AlcorFlashListHeader;

1

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:

1

2

3

4

5

6

<b>typedef</b><b>struct</b>{

unsignedcharvendor[16];

unsignedcharpartno[32];

unsignedcharid[6];

unsignedcharunk1[0xb];

unsignedcharCE;

1

....

1

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

#include &lt;iostream&gt;

#include &lt;stdio.h&gt;

#include &lt;string.h&gt;

#include &lt;stdlib.h&gt;

#define LOBYTE(v) *((unsigned char*)&amp;v)

#pragma pack(push, 1)

<b>typedef</b><b>struct</b>{

charheaderMagic[16];

intunk1;

intunk2;

intunk3;

intunk4;

intunk5;// 1

intversion;//Confirmed?

intentry_size;// Confirmed?

intentry_count;

}AlcorFlashListHeader;

<b>typedef</b><b>struct</b>{

unsignedcharvendor[16];

unsignedcharpartno[32];

unsignedcharid[6];

unsignedcharunk1[0xb];

unsignedcharCE;

/*unsigned char unk2[14];

unsigned char cache_enabled;*/

unsignedcharunk[0x260-(1+0xb)];

}AlcorFlashListEntry;

#pragma pack(pop)

// It seems to be some kind of block cipher using 0x100 ( 256 bytes) blocks