From bill.cummins@cingular.com Fri Jun 22 08:49:28 2001 Date: Wed, 20 Jun 2001 10:33:34 -0500 From: "Cummins, Bill" To: "'project@honeynet.org'" Cc: "BOCHONKO, WALLY G (SBMS)" , "'wrc@pobox.com'" Subject: Scan of the Month -- June (#16) Too easy. You gave it away by saying it was a rootkit. This implies that it is either trivial (simple repeating-key XOR, crypt() ), or non-trivial (DES, RC4, etc.). Since one of the goals is to decrypt it, it must be trivial. Here's some short answers to the questions: 1. Algorithm XOR, with one byte (0xFF), or bit (1), depending on your point of view. 2. Determination A quick frequency check of the supplied data shows that it is text of some sort. Ciphertext this short makes a freq analysis iffy, unless it is text with lots of spaces or newlines. What luck! hexdump -f hexa somefile | sort | uniq -c | sort -nr | head #(2-byte combos) 7 d091 7 969d 7 8fd0 7 8c8f 7 8c8b 6 d0ce 6 cfd0 6 9bd0 6 9196 6 899a hexdump -f hexb somefile | sort | uniq -c | sort -nr | head #(1-byte) 48 8c 45 d0 34 8f 30 d3 29 91 28 8b 27 93 24 9a 24 96 18 f5 ...Obviously text. Obviously simple XOR, crypt() would show -some- randomness in a file this short. 3. Decryption ---SNIP--- [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,s n.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 ---SNIP--- >From the previous freq analysis, it's obviously XOR, and obviously text. The key must be short, since the 2-byte pairs have such a high frequency. At a glance, the key is probably 4 bytes or less to get that much out of 532 bytes of ciphertext, even without looking at the pair offsets to make a better determination. Assuming the text is ascii (source code, sniff log, config file), the fact that every significant bit is '1' implies that the key is -not- ascii, or ascii rotated so that every msb is fortuitously a '1'. I'm lazy. I snagged xor-analyze-0.1 to automate some keyspace searching and comparisons. It took some hacking to actually make it work correctly(ish). Once it was working, it came up with the key 0xff (even though it figured on a keylength of 4 bytes, my guess of a max length). This looked good to me, so I applied it against the first few bytes of the ciphertext. Once I got to the 'e' of [file], I knew it was correct. I decrypted the rest of the file w/the key. 4. Purpose It's the config file for a rootkit. It lets the running processes know what to hide from whom, along with the 'secret password', probably for a backdoored /bin/su. It's encrypted/obfuscated to guard against prying eyes. 5. Lessons -Crappy code still works, with enough toil. -It's better to encrypt for real, even if you have to have the key in memory. -Never use the defaults in a rootkit. 6. Time It took half an hour to finally decrypt the file. It took an hour to fix xor-analyze. -Bill -- William R. Cummins ** Cingular GLR Information Security 847-765-5315 ** bill.cummins@cingular.com