Decrypting cryptelf encrypted binarys (problems with XOR) by h4z4rd [001] What is this abouth? [010] What is wrong? [011] Finfing pass... [100] END [001] What is this abouth? Cryptels is a nice and simple utility that allows you to encrypt .text section of ELF files thus disallowing you to run binary without proper password. Binary is encrypted xor-ing .text section with password: ============== void __crypttext(unsigned long _mapped,char * _key) { unsigned long _text; int _textsize; unsigned long _textaddr; int i; _textsize = __gettextsize(_mapped); _textaddr = (_mapped + __gettextoffset(_mapped)); for(i=0;i<_textsize;i+=8) { /* xor it with the key */ *(long long *)(_textaddr + i) ^= *(long long *)(_key); } } =============== [010] What is wrong? All this is nice but what is nature of xor? If we xor 0000 with 0110 (eg. pass) we will get 0110, our password. This is not a problem except we xor nothing, and reveal our password. Are there in .text section null bytes?? Ofcourse, and this means that we could get password, but this isn't so easy, because we can't recognize password betwean all that characters. Now i will pwd program encrypt with hazard as password: This is how looks hex of clean pwd: . . . . '|' . . . . '|' . . . . '|' U . . S '|' P . . . '|' . . [ . '|' . z - . . . . . '|' . . . . '|' . t . . '|' . . ] . '|' . . . . '|' . . . . '|' . . . . [note: '|' is added for aligment so you can notice easyer ;)] And same part of encrypted pwd: . . ~ i '|' . . . . '|' . . . . '|' ' . . S '|' 8 . z a '|' r d Q . '|' . . W a r . . . '|' h a z . '|' . . . . '|' . . ' . '|' . . . . '|' . . . . '|' . . . . We can see that in previously blank spaces we got some chars, looking a bitt better we can see that chars we got are hazard. The reason we don't see whole password is in the for(){} (if you look a bit you will see). If we look trough hexdump we can notice 'hazard' very often, some where even whole password. [011] Finfing pass... But what if you can't get original file and match? If you run strings on encrypted you will get nice output of string occuring in binary. example: ======= ..... unimportant ..... GLIBC_2.1.3 GLIBC_2.0 GLIBC_2.2 85( ez5\h zardQ haza ,Ebq ,bza< lEzard lEzard DLezard Lazar ,Erdrd ~Erd $iaza lEzard .... pretty much the same .... ======== We can notice that below definition of glibc version occurs our password. If a password is longer than 5 chars we won't find it whole, but splitted in 2 lines. Run on few examples and you will find password always few lines below glibc, you just have to stick two patterns together. Btw you will always have to stick it by looking and overlaping parts: eg. you have patterns (few lines below glibc schit): zardQ haza ,Ebq ,bza< allways go from below to up and look: 1: ,bza< 2: ,Ebq 3: haza 4: zardQ this is wery difficult ;) 1 and 2 probably aren't because people probably won't use this like password, leaving us 3 and 4. You can notice that 3 and 4 have some chars inncomet 'za' thus this is probably our password 'haza+zardQ'='hazardQ' almost always you will find some mad chars like "~°^#$'ST" sticked to patterns because of aligment. For us works thing that users often choose sth. that has sence, not "!d]&#$&" for password, even if they use you can find it out by looking for occurences of that patterns or bruteforcing first few lines. You can find every password in ~10 attempts which is ~5-10 min. Finally: [gljiva] [cryptelf]$> ./pwdcrypted password: hazard /home/hazard/programs/cryptelf [gljiva] [cryptelf]$> [100] END This schit can be actualy used for decryption, it is also possible that password can be found much simplyer ;). Greets: to all who read this, and learn sth. ps: sorry for awful english (gnglish)