Didier Stevens


Translate.py is a Python script to perform bitwise operations on files (like XOR, ROL/ROR, …). You specify the bitwise operation to perform as a Python expression, and pass it as a command-line argument.

translate.py malware malware.decoded ‘byte ^ 0x10’

This will read file malware, perform XOR 0x10 on each byte (this is, expressed in Python: byte ^ 0x10), and write the result to file malware.decoded.

byte is a variable containing the current byte from the input file. Your expression has to evaluate to the modified byte. For complex manipulation, you can define your own functions in a script file and load this with translate.py, like this:

translate.py malware malware.decoded ‘process(byte)’ process.py

process.py must contain the definition of function process. Function process must return the modified byte.

Another variable is also available: position. This variable contains the position of the current byte in the input file, starting from 0.

If only part of the file has to be manipulated, while leaving the rest unchanged, you can do it like this:

    def process(byte):
        if position >= 0x10 and position < 0x20:
            return byte ^ 0x10
            return byte

This example will perform an XOR 0x10 operation from the 17th byte till the 32nd byte included. All other bytes remain unchanged.

Because Python as built-in shift operators (<< and >>) but no rotate operators, I’ve defined 2 rotate functions that operate on a byte: rol (rotate left) and ror (rotate right). They accept 2 arguments: the byte to rotate and the number of bit positions to rotate. For example, rol(0x01, 2) gives 0x04.

translate.py malware malware.decoded ‘rol(byte, 2)’

Another function I defined is IFF (the IF Function): IFF(expression, valueTrue, valueFalse). This function allows you to write conditional code without an if statement. When expression evaluates to True, IFF returns valueTrue, otherwise it returns valueFalse.

translate.py malware -o malware.decoded “IFF(position >= 0x10 and position < 0x20, byte ^ 0x10, byte)”

translate_v2_0_0.zip (https)
MD5: 31739EEE90E303A8DA5A995344BA6F5B
SHA256: CFB11380C4193E91D7843F195D9EA086A59829F9CF3DF4016C12ACE8378B052C



  1. This is _very_ inefficient:
    def rol(byte, count):
    while count > 0:
    byte = (byte <> 7) & 0xFF
    count -= 1
    return byte

    This should work faster:
    def rol(byte, count):
    byte = (byte <> (8 – count)) & 0xFF
    return byte

    Comment by io — Thursday 10 July 2008 @ 15:58

  2. I believe you wanted to write this:

    def rol(byte, count):
    byte = (byte << count | byte >> (8 – count)) & 0xFF
    return byte

    You’ll be surprised by the gain in performance: about 10%
    Translating a 3MB file with the original ROL (rolling 4 bits) takes 168 seconds, translating the same file with the faster ROL takes 155 seconds.

    There is a huge overhead in the translation of each byte by the eval function:
    outbyte = eval(command)

    For every byte, Python has to parse, compile and execute the command. Parsing and compiling takes much more time than the loop in the original ROL command. This is _very_ ineffecient, but _very_ flexible. You can provide your own Python expression without having to edit the translate program.

    I used a loop in the ROL and ROR commands for didactic reasons. Manipulating bits is very foreign for most people, even programmers. I believe my version is more readable and understandable, and thus extendable by other people.

    But you’re right, removing inner loops adds to the performance. But in this specific case, most CPU cycles go to the eval function, and not to the loop.

    Anyways, thanks for your comment, I’ll have to think about how to include your code. Maybe I can leave the original ROL and use your code for the ROR ;-)

    Comment by Didier Stevens — Thursday 10 July 2008 @ 21:05

  3. I think the posting process somehow managed to steal some of my text (especially since the first function is copy&pasted from your post), but yes, that’s what I wanted to write. :)

    And _especially_ for didactic reasons I think the code should be as good as possible, since other people are learning from it. The folks who don’t understand bit operations should probably stay away from decryption & malware analysis altogether… might do more harm than good. ;)

    As for the optimality of the rest of the code, I’ve only skimmed it I’m affraid. I was actually looking for an efficient way of doing ROL/ROR in .py, and that’s how I stumbled over your code. I have plenty of experience with Python, and by accident I work in the malware anlysis industry myself. :) Getting back to the efficiency issue, I’m probably going to write a ROL/ROR module in C/asm to make it efficient enough. That code might even be worth including…


    Comment by io — Friday 11 July 2008 @ 12:27

  4. hi,

    this is nice … thanks

    Comment by sanjeev — Wednesday 21 April 2010 @ 10:40

  5. Hey Didier,

    I used the code from translate to build a Mcafee .BUP file decoder. Here’s the code:

    # Mcafee .BUP File XOR converter
    # Based on Didier Stevens “Translate.py”
    # http://blog.didierstevens.com/programs/translate/
    # Usage: nobup.py file.bup
    import sys

    if len(sys.argv) != 2:
    print ‘usage: ./nobup.py file.bup’
    encoded = open(sys.argv[1], ‘rb’)
    bup = (sys.argv[1] + ‘.decoded.bin’)
    decoded = open(bup, ‘wb’)
    command = ‘byte ^ 0x6A’
    position = 0
    while True:
    inbyte = encoded.read(1)
    if not inbyte:
    byte = ord(inbyte)
    outbyte = eval(command)
    position += 1

    Comment by Lucas Lyon — Saturday 10 July 2010 @ 2:22

  6. […] time ago, Chris John Riley reminded me of a program I had written, published … and forgotten: translate.py. Apparently, it is used in SANS […]

    Pingback by Update: translate.py | Didier Stevens — Wednesday 16 July 2014 @ 19:37

RSS feed for comments on this post. TrackBack URI

Leave a Reply (comments are moderated)

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

The Rubric Theme. Blog at WordPress.com.


Get every new post delivered to your Inbox.

Join 225 other followers

%d bloggers like this: