2009
12.07

With the next TitanEngine release just around the corner we decided to do a light an interesting analysis of a simple executable password protection. Today's focus is on LCCrypto a simple example which will show us the general security and vulnerabilities of such and similar tools.

Now it theory only one password should be able to unlock such protected application and allow its execution without any possibility of removing the protection without the correct password. Well that's the theory behind such tools but they themselves have a weakness too because there still must be a way for the application to check the validity of the inputted password. So regardless of the protection executable password protection solution must do one of the following:

  • Compare passwords or password hashes to determine whether or not to execute the file
  • Use the inputted password for code decryption and verify the decrypted content by hashing

So, not a lot of options to choose from. First model would be the least secure since no content is encrypted and the second most secure requiring password bruteforce to be removed. Lets see what we are dealing with in LCCrypto's case. Entry point of the protected file looks like this:

  MOV EAX,DWORD PTR SS:[ESP] ;Pointer to ExitProcess API
  AND EAX,FFFF0000
L002:
  CMP DWORD PTR DS:[EAX],905A4D
  JE L006
  SUB EAX,1000
  JMP L002
L006:
  PUSH EBP

Very simple way to get the kernel base most commonly used in malware which could flag this sample as malicious by some anti-virus vendors. Following this we have:

  MOV EBP,EAX
  ADD EAX,DWORD PTR DS:[EAX+3C]
  MOV EDI,DWORD PTR DS:[EAX+78]
  ADD EDI,EBP
  MOV ESI,DWORD PTR DS:[EDI+20]
  ADD ESI,EBP
  XOR EDX,EDX
L007:
  MOV EAX,DWORD PTR DS:[ESI]
  ADD EAX,EBP
  CMP DWORD PTR DS:[EAX],50746547
  JNZ L025
  CMP DWORD PTR DS:[EAX+4],41636F72
  JNZ L025
  CMP DWORD PTR DS:[EAX+8],65726464
  JNZ L025
  CMP WORD PTR DS:[EAX+C],7373
  JNZ L025
  MOV EAX,DWORD PTR DS:[EDI+24]
  ADD EAX,EBP
  MOVZX EBX,WORD PTR DS:[EAX+EDX*2]
  MOV EAX,DWORD PTR DS:[EDI+1C]
  ADD EAX,EBP
  MOV EAX,DWORD PTR DS:[EAX+EBX*4]
  ADD EAX,EBP
  MOV DWORD PTR DS:[407408],EAX
L025:
  ADD ESI,4
  INC EDX
  CMP EDX,DWORD PTR DS:[EDI+18]
  JNZ L007

Another code which is used to locate GetProcAddress API pointer. This is crucial since that API and already located kernel base are all that this protection needs to locate all other needed APIs to create password input dialog and process it. Code that creates the window and its elements is located just after the code locates all needed APIs. Code that is of interest is here:

  PUSH DWORD PTR DS:[407004]
  CALL NEAR DWORD PTR DS:[407410] ;FreeLibrary
  PUSH DWORD PTR DS:[407000]
  CALL NEAR DWORD PTR DS:[407410] ;FreeLibrary
  CMP BYTE PTR DS:[407881],0
  JE L008
  MOV EAX,004012C0 ;OriginalEntryPoint
  JMP NEAR EAX
L008:
  PUSH 0
  CALL NEAR DWORD PTR DS:[407414] ;ExitProcess

This is what happens when the window message processing loop just above this exits, and that will happen when the created window associated with that message processing loop terminates by window closing. Which means that if the byte at address 0x00407881 isn't set to zero LCCrypto will pass the code execution to original entry point which in this case isn't encrypted at all. Patching this compare in memory and closing the window would do the trick. Removing the protection completely would be as easy as setting the entry point address in the PE header to 0x000012C0. Normally our work would be done here, but lets dig in just a little bit more.

  PUSH 10
  PUSH 0040776E
  PUSH 64
  PUSH DWORD PTR SS:[EBP+8]
  CALL NEAR DWORD PTR DS:[407460] ;GetDlgItemTextA
  CALL 00407FF9 ;Calculate CRC32
  LEA EBX,DWORD PTR DS:[40776E]
  CALL 00408021 ;Update CRC32
  CMP DWORD PTR DS:[40775E],EAX ;Compare password CRC32
; DS:[0040775E]=0E1A88EF
  SETE BYTE PTR DS:[407881] ;Set the correct password switch

This code bit here processes the inputted password. As we can see from the code above inputted password is hashed with CRC32 and that value is compared with the value 0x0E1A88EF, and that means that hash for the password must be 0x0E1A88EF for protection to pass the control to original code. Now, leaving alone the fact that we can patch the file, think about what we can do to legitimately start the application. Bruteforce the hash? What about make a string that has the same one?

CRC32 algorithm collides which means that we can create such a string. Without going into coding a program that can do that we use a PeID plugin called CRC32 made by Gelios on a simple text file containing only the string "pwd". After the file's CRC32 has been set to 0x0E1A88EF our string "pwd" becomes "pwd€va" which is a string with the CRC32 hash we need. Entering such string into program will fool it into thinking that is the original password making LCCrypto execute the file normally.

We didn't do any coding today because it wasn't necessary. However we did investigate the security of one executable password protection and saw all the flaws its has. Next time we return to this topic we will do some coding in order to make a bruteforce engine that will recover the password used to protect the file. Until next time...

LCCrypto
Download protected sample

VN:F [1.9.3_1094]
Rating: +1 (from 1 vote)
  • Share/Bookmark
  1. [...] This post was mentioned on Twitter by Keith, ap0x. ap0x said: Do you know how your executable password protection solution works? Read about it here: http://bit.ly/7UvwWH [...]