{=========================================} DECRYPTION AND ANALYSIS OF A FILE {=========================================} pingouin 6 June 2001 In this document I will describe my analysis of an 'encrypted' file found on a compromised solaris system. I will first describe the 'tricks' I used to decrypt the file, then I'll analyse (as much as I can) this file. ------------------------------------------- Part 1 - Encryption algorithm determination ------------------------------------------- Step 1 : download the file, check md5 signature and decompress. At that step we can notice it's a fairly small file, and we can guess it's a text file. Actually we have to guess some more to find the encryption algorithm. Step 2 : first analysis of the file. When using less on the file, we notice reccurent structures. Using hexdump on it, we can see that the "distributions" of differents characters is rather focused. I conclude that this file is likely to be encrypted using a monoalphabetic algorithm (not sure if that's the exact name!). What do I mean by "monoalphabetic algorithm"? If this file is a text file, every byte is a different character. In a monolaphabetic algorithm it is possible to write a table made of 256 distincts elements ranging from 0 to 255, so that table[clear_text] = cypher. That means that every byte of clear text can be associated to a 'cyphered' byte, and vice-versa. My goal is then to find this table. ---------------------------------------- Part 2 - Encryption method determination ---------------------------------------- Now that we assume what kind of encryption algorithm it is, it's time to find the 'table'. I write a little program to see the 'spread' of the file (see Annex). The output is : character -> Number present in file (ASCII equivalent) 0 -> 0 () 1 -> 0 () 2 -> 0 () 3 -> 0 () 4 -> 0 () 5 -> 0 () 6 -> 0 () 7 -> 0 () 8 -> 0 () 9 -> 0 ( ) 10 -> 0 ( ) 11 -> 0 ( ) 12 -> 0 ( ) 13 -> 0 ( ) 14 -> 0 () 15 -> 0 () 16 -> 0 () 17 -> 0 () 18 -> 0 () 19 -> 0 () 20 -> 0 () 21 -> 0 () 22 -> 0 () 23 -> 0 () 24 -> 0 () 25 -> 0 () 26 -> 0 () 27 -> 0 () 28 -> 0 () 29 -> 0 () 30 -> 0 () 31 -> 0 () 32 -> 0 ( ) 33 -> 0 (!) 34 -> 0 (") 35 -> 0 (#) 36 -> 0 ($) 37 -> 0 (%) 38 -> 0 (&) 39 -> 0 (') 40 -> 0 (() 41 -> 0 ()) 42 -> 0 (*) 43 -> 0 (+) 44 -> 0 (,) 45 -> 0 (-) 46 -> 0 (.) 47 -> 0 (/) 48 -> 0 (0) 49 -> 0 (1) 50 -> 0 (2) 51 -> 0 (3) 52 -> 0 (4) 53 -> 0 (5) 54 -> 0 (6) 55 -> 0 (7) 56 -> 0 (8) 57 -> 0 (9) 58 -> 0 (:) 59 -> 0 (;) 60 -> 0 (<) 61 -> 0 (=) 62 -> 0 (>) 63 -> 0 (?) 64 -> 0 (@) 65 -> 0 (A) 66 -> 0 (B) 67 -> 0 (C) 68 -> 0 (D) 69 -> 0 (E) 70 -> 0 (F) 71 -> 0 (G) 72 -> 0 (H) 73 -> 0 (I) 74 -> 0 (J) 75 -> 0 (K) 76 -> 0 (L) 77 -> 0 (M) 78 -> 0 (N) 79 -> 0 (O) 80 -> 0 (P) 81 -> 0 (Q) 82 -> 0 (R) 83 -> 0 (S) 84 -> 0 (T) 85 -> 0 (U) 86 -> 0 (V) 87 -> 0 (W) 88 -> 0 (X) 89 -> 0 (Y) 90 -> 0 (Z) 91 -> 0 ([) 92 -> 0 (\) 93 -> 0 (]) 94 -> 0 (^) 95 -> 0 (_) 96 -> 0 (`) 97 -> 0 (a) 98 -> 0 (b) 99 -> 0 (c) 100 -> 0 (d) 101 -> 0 (e) 102 -> 0 (f) 103 -> 0 (g) 104 -> 0 (h) 105 -> 0 (i) 106 -> 0 (j) 107 -> 0 (k) 108 -> 0 (l) 109 -> 0 (m) 110 -> 0 (n) 111 -> 0 (o) 112 -> 0 (p) 113 -> 0 (q) 114 -> 0 (r) 115 -> 0 (s) 116 -> 0 (t) 117 -> 0 (u) 118 -> 0 (v) 119 -> 0 (w) 120 -> 0 (x) 121 -> 0 (y) 122 -> 0 (z) 123 -> 0 ({) 124 -> 0 (|) 125 -> 0 (}) 126 -> 0 (~) 127 -> 0 () 128 -> 0 () 129 -> 0 () 130 -> 0 () 131 -> 0 () 132 -> 0 () 133 -> 0 () 134 -> 1 () 135 -> 1 () 136 -> 2 () 137 -> 11 () 138 -> 7 () 139 -> 28 () 140 -> 52 () 141 -> 11 () 142 -> 1 () 143 -> 34 () 144 -> 10 () 145 -> 29 () 146 -> 2 () 147 -> 28 () 148 -> 0 () 149 -> 0 () 150 -> 24 () 151 -> 6 () 152 -> 3 () 153 -> 14 () 154 -> 24 () 155 -> 18 () 156 -> 12 () 157 -> 14 () 158 -> 9 () 159 -> 0 () 160 -> 6 () 161 -> 0 () 162 -> 4 () 163 -> 0 () 164 -> 4 () 165 -> 0 () 166 -> 0 () 167 -> 0 () 168 -> 0 () 169 -> 0 () 170 -> 1 () 171 -> 0 () 172 -> 1 () 173 -> 1 () 174 -> 0 () 175 -> 0 () 176 -> 0 () 177 -> 0 () 178 -> 0 () 179 -> 0 () 180 -> 0 () 181 -> 0 () 182 -> 0 () 183 -> 0 () 184 -> 0 () 185 -> 0 () 186 -> 1 () 187 -> 0 () 188 -> 0 () 189 -> 0 () 190 -> 0 () 191 -> 0 () 192 -> 0 () 193 -> 0 () 194 -> 14 () 195 -> 0 () 196 -> 0 () 197 -> 4 () 198 -> 0 () 199 -> 3 () 200 -> 2 () 201 -> 9 () 202 -> 1 () 203 -> 2 () 204 -> 3 () 205 -> 2 () 206 -> 13 () 207 -> 18 () 208 -> 45 () 209 -> 5 () 210 -> 0 () 211 -> 30 () 212 -> 0 () 213 -> 0 () 214 -> 0 () 215 -> 0 () 216 -> 0 () 217 -> 0 () 218 -> 0 () 219 -> 0 () 220 -> 0 () 221 -> 0 () 222 -> 0 () 223 -> 0 () 224 -> 0 () 225 -> 0 () 226 -> 0 () 227 -> 0 () 228 -> 0 () 229 -> 0 () 230 -> 0 () 231 -> 0 () 232 -> 0 () 233 -> 0 () 234 -> 0 () 235 -> 0 () 236 -> 0 () 237 -> 0 () 238 -> 0 () 239 -> 0 () 240 -> 0 () 241 -> 0 () 242 -> 0 () 243 -> 0 () 244 -> 0 () 245 -> 22 () 246 -> 0 () 247 -> 0 () 248 -> 0 () 249 -> 0 () 250 -> 0 () 251 -> 0 () 252 -> 0 () 253 -> 0 () 254 -> 0 () 255 -> 0 () Looking at that it becomes clear that the table is 'continuous', 'regular'. That means that if the plain text character 100 is associated to 54, it is likely that 101 would be associated with 55 or 53, but not 212. Hypothesis 1 : the file is ROT-13 or ROT-xxx. Known as the "Jules Cesar" code, this algorithm rotates the characters. Thus if a becomes g, b becomes h. Verification : I wrote a program that tries all the 255 rotations and i piped the output to less. It's very fast to eye-scan the output and notice it's only junk. Hypothesis 2 : the file is XORed. That means that we have a key (let's say it's size is 1 byte) and cypher = clear XOR key, and clear= cypher XOR key. XOR is widely used to quick scramble data, because it's fast and easy to implement. Verification : I modified the same program so that it XOR instead of rotate, and scanned the output the same way. Bingo !!! With a key of 255, we find the real text. ------------------------ Part 3 - File decryption ------------------------ See annex to get the decrypion program. The output is : ***BEGINNING OF THE OUTPUT*** [file] find=/dev/pts/01/bin/find du=/dev/pts/01/bin/du ls=/dev/pts/01/bin/ls file_filters=01,lblibps.so,sn.l,prom,cleaner,dos,uconf.inv,psbnc,lpacct,USER [ps] ps=/dev/pts/01/bin/psr ps_filters=lpq,lpsched,sh1t,psr,sshd2,lpset,lpacct,bnclp,lpsys lsof_filters=lp,uconf.inv,psniff,psr,:13000,:25000,:6668,:6667,/dev/pts/01,sn.l,prom,lsof,psbnc [netstat] netstat=/dev/pts/01/bin/netstat net_filters=47018,6668 [login] su_loc=/dev/pts/01/bin/su ping=/dev/pts/01/bin/ping passwd=/dev/pts/01/bin/passwd shell=/bin/sh su_pass=l33th4x0r ffffffff ***END OF THE OUTPUT*** -------------------------------------------------- Part 4 - purpose of the file, why was it encrypted -------------------------------------------------- This file looks like a rootkit configuration, telling the rootkit programs what to hide, and where the trojaned binaries are hiding. In the [file] section, there are the file-related trojanned binaries : find, du and ls. They hide chains matching the file_filter list. The [ps], [netstat] and [login] sections are just the same for the other binaries. We can notice that there is a su backdoor, with password (how original) l33th4x0r. It looks quite possible that this file was called 'uconf.inv', because it is the only file that should not be displayed by ls and find that is named like a conf file. Why was it encrypted? My guess is that it was encrypted to prevent direct match using the strings command, or grep. ----------------- Part 5 - Lessons! ----------------- Argh sounds like a litteracy teacher asking you what is to be remembered of a text! I guess the lesson is that simple cyphers are just too simple, and easy to break when you know where to look, but such a crude method would help the rootkit to hide. ------------------- Part 6 - Time Spent ------------------- Part 1 : 1 minute. Part 2 : 15 minutes. Part 3 : 1 minute. Part 4 : 3 minutes. Part 5 : Uhhh still thinking about that! -------------- Bonus question -------------- A little google search with su_pass [netstat] and uconf.inv shows us 1 result. Looking at it we can see that someone is having a very similar situation with "SunOS Rootkit v2.5 (C) 1997-2001 Tragedy/Dor". On http://www.sans.org/y2k/the_compromise.htm, we find our friend uconf.inv encrypted exactly the same way. They say the rootkit is Adore, a linux LKM based Rootkit. My guess is that it's adore, and the l33th4x0r didn't knew linux and solaris were two different things (perhaps the rootkit can be compiled on different arch?). ------------------ Annex : my program ------------------ This one decrypts and shows the 'scattering' #include int main(void) { int c; char table[255]; char key; FILE * fichier; fichier = fopen("somefile","r"); for(c=0;c<256;c++) table[c] = 0; while ((c=getc(fichier))!=EOF) { table[c]++; printf("%c",255 - c); } for(c=0;c<256;c++) printf("%d -> %d (%c)\n",c,table[c],c); fclose(fichier); }