Decrypt DATA statically using IDAPYTHON

Hi Guys

Today, I would like to share the use of IDAPyhton for you to do automation during your reversing some codes. There are use cases where IDAPhyton will help you so much on the process. I am gonna share one of them

The use case that I developed is to decrypt a base64 encrypted string. I wrote a simple application like below

#include <iostream>

char src[64] = { 'u','f','Y','Y','o','f','Z','H','p','x','P','V','e','G','p','7','E','s','Q','7','9','G','k','0' };

int main()
{
    std::cout << "Let Statically Decrypt Base 64 RC4: ";
    std::cout << src;
}

here below the code in IDA

The idea is to decrypt the string that is pointed by the offset char * src in the data segment statically without the need to run this application in debug mode.

IDAPython

IDAPython is an extended capability of IDA Pro that enable you to do scripting with python 2.7. You can script it in IDA within this box

I would suggest you to code the python in another IDE (e.g pycharm) and paste them to this small box just for your convinience. There tons of IDA API that you can use to interact with IDA while you do your coding.

You can get it from https://www.hex-rays.com/products/ida/support/idapython_docs/

Lets Decrypt

As we know that the encryption that applied to the string is RC4 where the data is based64 so that we need to reverse it. Here below the steps

  1. You need to find the main function by looping the entire function that is available in IDA using API Functions()
  2. After you get the Main Function then you have to loop the address within this function to check the existense of encrypted string using API func = idaapi.get_func(funcAddr) and func.startEA and func.endEA
  3. You need to find the Operation of each line that consist of “char *
  4. Once it found char * then we need to extract the sequence of string that it point to in the data segment
  5. once the string is extracted then we need to do base64 decode and pass the result to RC4 decryption

All the high level above will look like this in the python code

import idautils
import idaapi
import binascii
import base64

def rc4crypt(key, data):
    x = 0
    box = range(256)
    for i in range(256):
        x = (x + box[i] + ord(key[i % len(key)])) % 256
        box[i], box[x] = box[x], box[i]
    x = 0
    y = 0
    out = []
    for char in data:
        x = (x + 1) % 256
        y = (y + box[x]) % 256
        box[x], box[y] = box[y], box[x]
        out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))
    return ''.join(out)

for funcAddr in Functions():
    funcName = GetFunctionName(funcAddr) #get the list address of the function 
    if funcName == '_main':
        func = idaapi.get_func(funcAddr) #construct the func structure
        addr = func.startEA #get the start address
        while addr < func.endEA: #loop untill the last address of the main funct
            if idc.GetOpnd(addr, 0).find("char *") > 0: #find the instruction with char*
                base64String = ""
                newAddr = idc.GetOperandValue(addr, 0) #get the address of value
                while True:
                    try:
                        a =  idc.GetOpnd(newAddr, 0) #get the char in hex
                        a = a[:-1] #remove the trailing H in hex value
                        if len(a) == 0: #stop the the loop when the more char
                            break
                        temp =  str(a.decode("hex")) #convert from hex to string
                        base64String = base64String + temp #append char to string
                    except:
                        break
                    newAddr = newAddr + 1 #increase one byte address for each loop
                print "Extracted String : " + base64String #show the extracted value
                message_bytes = base64.b64decode(base64String) #decode base64 the string to byte array
                result = rc4crypt("Key", message_bytes) # run the RC4 decryption
                print "Decrypted String : " + result #print the decrypt result
            addr = idc.NextHead(addr)

Function() will return all list of the extracted function address that has been analyzed by IDA

GetFunctionName(functionAddress) will return the function name. The parameter of this function is functionAddress

idc.GetOpnd(Address, 0) will return the operand of each line address in the a function of address supplied. You can specify the first operand of second operand in each instruction by specifying the second parameter in the function for example mov ecx, 30h

1. idc.GetOpnd(Address, 0) will return ecx
2. idc.GetOpnd(Address, 1) will return 30h

idc.GetOperandValue(addr, 0) will return the value of the operand it points to. We will use this API to return the value from the data segment

idc.NextHead(addr) will give you the next address of the current. It helps us to loop sequence of address.

The above code will not work when the string has been change to array by IDA which is like this

You have to change it to data so that each char will have the its own address by following this steps below

After you changed them into data then the view will become like this

Now you can paste the code above into IDA script and press enter twice

We can above when the script is run then it will do the decryption as highlighted above.

We have successfully decrypted the string without having to run the application in debug mode.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s