The .so file is a compiled library, in most cases from C or C++ source code. .so stands for Shared Object, it doesn't have anything to do with obfusation, it just means someone wrote parts of the app in C.
In some cases, there is existing C code and it's just easier for the programmer to build a JNI interface to call the library from java; in other cases, ...
This is for position independent code. The call 0xe50b instruction pushes the address of the next instruction, and then jumps. It jumps to the immediately following instruction, which has no effect. The next instruction, pop eax, loads its own address into eax (as it was the value pushed by call).
Further down it uses an offset from eax:
mov eax, dword [ds:...
The organisation OpenSecurityTraining offers free training materials under creative commons type licenses. Many of the training's are videos, while others are slide decks and related class materials (scripts, malware samples and so on). The course-ware comes under 3 categories and features the following items (Which I have edited to include the RE related ...
The choice of a compiler has minimal effects on the difficulty to reverse engineer your code. The important things to minimize are all related to information leaks from your code. You want to at least disable any runtime type information (RTTI). The leakage of type information and the simplicity of the instruction set of the virtual machine is one ...
The paper Static Analysis of x86 Executables explains overlapping instructions quite well. The following example is taken from it (page 28):
0000: B8 00 03 C1 BB mov eax, 0xBBC10300
0005: B9 00 00 00 05 mov ecx, 0x05000000
000A: 03 C1 add eax, ecx
000C: EB F4 jmp $-10
000E: 03 C3 add eax, ebx
0010: C3 ret
From this paper by Timea Laszlo and Akos Kiss :
The basic method for ﬂattening a function is the following.
First, we break up the body of the function to basic blocks, and then we put all
these blocks, which were originally at diﬀerent nesting levels, next
to each other.
The now equal-leveled basic blocks are encapsulated in
a selective structure (a switch ...
Besides Guntram's suggestions, check out the retargetable decompiler aka retdec. It can decompile the binary to Python or C code. At least for me, it reads easier than pure assembly (and it works for ARM binaries).
It works very well for sketching you the rough workings of the shared object.
A plugin for select IDA versions exists, but the main limitation ...
I've been dissecting the firmware for another type of embedded device for a while and thought I'd see if I could find anything out. After a few hours I figured it out! There is a hard way and an easy way that I found only after digging the hard way. This is a long post, but I hope it will help others in similar ventures.
A little Googling and I found ...
JS-Unpack (see also blog)
Advanced obfuscated ...
Your question title indicates merely reversing minified code, and not necessarily understanding it. But if you are attempting to gain an understanding of it, Opera Dragonfly sounds like a ...
Here's some I've seen or heard about:
Stripping the section headers. A simple and fully legal action that stops GDB dead in its tracks. Does not work against some other debuggers (e.g. IDA). Can be done using the sstrip tool.
Using syscall function or direct syscalls instructions instead of calling specific functions like ptrace(). Can be defeated by ...
Here are my favorite. I started with Lena's tutorials, they are really awesome.
tuts4you - an endless amount of tutorials. I can highly recommend Lena's reversing for newbies
binary-auditing - Free IDA Pro Binary Auditing Training Material for University Lectures
An opaque predicate is an obfuscated condition, that, followed with a conditional operation, will make the analysis harder, and in some cases impossible until code is actually executed until that condition is evaluated.
This is used to disrupt static analysis (outcome is unpredictable) or emulation (to tell the difference between a real machine and an ...
The answers already in this thread are good ones. In a nutshell, an opaque predicate is "something that a program analysis might miss, if the program analysis is not sophisticated enough". Denis' example was based on the inverse of constant propagation, and served as an anti-checksum mechanism. Joxean's SetErrorMode example was an environment-based opaque ...
Here are tricks you can use when packaging your python app with a custom interpreter.
Remap the opcodes for the interpreter
Encrypt the pyc files (the custom interpreter decrypts before importing)
Remove access to co_code in the interpreter (delete the reference to co_code in the code_memberlist array declaration in codeobject.c of the interpreter)
For a good example of this obfuscation, check Apple's FairPlay code, e.g. iTunes or iOS libs. Here's a typical graph of a function which had this obfuscation applied:
As you can see, all edges between basic blocks - both conditional and unconditional - has been redirected to a dispatcher node which uses a new artificial variable to decide which block should ...
virtualizers usage in the wild
They are rarely used, and even worse (or better), rarely used in a useful way.
how they're used
Typically, it was the use of a virtualizer of over only the main function, or another binary packer, and both cases don't prevent analysis: if you bypass the virtualized packer code, then you get the original unpacked code anyway.
Binary packers alter the original binary data, and restore it (more or less) before execution.
Their different names depend more on their characteristic: it's difficult to clearly distinguish, as just putting an anti-debug and a Xor loop would make a packer also a protector and a cryptor.
extra packer code is executed
I'm the author of rdis and have put a bit of thought into this problem. I recommend taking a look at my blog if you have more questions after this.
I would also refer you to Andrew Ruef's blog post Binary Analysis Isn't. The key take away is we often attempt to understand our programs with the context of compilers, and not necessarily as just a continuum of ...
It's also known as the 'jump in the middle' trick.
most instructions take more than one byte to be encoded
they can take up to 15 bytes on modern CPUs
execution can start at any position as long as permissions are valid
so any byte following the first one of an instruction can be re-used to start another instruction.
This is a frequently used "trick" to determine the address of the instruction following the call, i.e. the call instruction pushes the return address on the stack, which in this case corresponds to 0xe50b. After the pop instruction, eax contains that address.
For instance, this idiom is used for position independent code (pic), but is also quite commonly ...
These techniques of mutating code (and still keeping it semantically equivalent) are known as polymorphic code.
The software that can achieve a mutations of the code is usually called a polymorphic engine. It is a quite widely used technique in Malware design to evade pattern-matching detection of the anti-virus software.
With these key words in hand (and ...
Using Malzilla, I was able to de-obfuscate this in ~30 seconds.
Step 2, you can optionally press the "Format Code" button to get a rudimentary re-formatting of the JS.
Step 3, check Override eval(), and click the Run script button.
You'll notice that in the output box, the de-...
Well, in your own programs, it's probably fine. But in a corporate setting its a maintenence nightmare without extremely good documentation and/or team continuity. Neither of which seems all that common in my experience.
I think a more general question might be, "are obfuscation techniques really all that useful?" I can understand minify for page ...
Now I cannot possibly know what the exact reason is here, but there is another very good reason, not mentioned so far, for using this kind of method: throwing off a disassembler during static analysis.
The mechanics of call $+5 have been discussed, so I'll assume they are known by now - otherwise refer to the other answers. Basically like with any call on ...
Not necessarily the predicate must be hard to evaluate. An opaque predicate is a condition which the result is known in advance by the programmer and that cannot be resolved statically (by a compiler, for example) and must be resolved dynamically.
An example I noticed in malware some years ago:
if ( SetErrorMode(1024) == 100 )
You can also try a dynamic approach by hooking APIs and observing arguments and return values. This will allow you to look at data going into crypto APIs, which may help a lot when dealing with network protocols. Check out the Frida instrumentation toolkit for an open source cross-platform solution (Android, iOS, Windows, Mac and Linux). There's a tutorial ...