Guy's 30 Reverse Engineering Tips & Tricks
During April I challenged myself to tweet 1 reverse engineering tip every day. For your viewing pleasure, here I aggregated all 30 tips.
Be sure to follow me @whtaguy for my latest tweets and more reverse engineering extravaganza.
Leave a comment on this post or tag me on Twitter - I reply pretty quickly :)
If the tweets aren't displayed properly (for example if there are no pictures), temporarily turn off tracker protection, which blocks loading the required resources from twitter
Tips & Tricks
Tip 1
Tip 2
Tip 3
Tip 4
Tip 5
Tip 6
Tip 7
Tip 8
Tip 9
Tip 10
Tip 11
Tip 12
Tip 13
Tip 14
Tip 15
Tip 16
Tip 17
Tip 18
Tip 19
Tip 20
Tip 21
Tip 22
Tip 23
Tip 24
Tip 25
Tip 26
Tip 27
Tip 28
Tip 29
Tip 30
*Reverse Engineering Tip 1/30*— Guy🏂 (@whtaguy) April 1, 2020
long branch-less functions w/many xors & rols are usually hash functions. IDA view of MD5 func:#BinReversingTips pic.twitter.com/cLSGfxNupK
-Reversing Tip 2/30-— Guy🏂 (@whtaguy) April 2, 2020
Building on the last tip, after finding a hash function, google its constant to identify the exact hash algorithm. #BinReversingTips pic.twitter.com/MJJIBY9pde
-Reversing Tip 3/30-— Guy🏂 (@whtaguy) April 3, 2020
Find the function controlling authentication in any exe by diff'ing the execution trace of a valid vs failed login. Traces will split right after the auth check >> pic.twitter.com/h5QpLnSRiZ
You can use Lighthouse to conveniently visualize trace data and operate on multiple traces showing their shared & unique trace paths https://t.co/iXY0IHY6Q7 #BinReversingTips pic.twitter.com/Ctr5pPDFFv— Guy🏂 (@whtaguy) April 3, 2020
-Reversing Tip 4/30-— Guy🏂 (@whtaguy) April 4, 2020
Use a function's neighboring code to understand its functionality:
Devs group related funcs together && compilers like to keep the order of funcs from src to exe ⇒ related funcs are closely grouped in the exe#BinReversingTips pic.twitter.com/DZBRYqLjDn
-Reversing Tip 5/30-— Guy🏂 (@whtaguy) April 5, 2020
Hate updating breakpoint addrs each time a module loads w/a new base? Patch the exe/dll header to disable the DYNAMIC_BASE flag for a static base addr https://t.co/zS84XU3zbX #BinReversingTips
-Reversing Tip 6/30-— Guy🏂 (@whtaguy) April 6, 2020
When reversing C++: Use “virtuailor” to *automatically* create class vtables & add xrefs to virtual funcs. It uses runtime inspection to evaluate func addrs to do its magic ✨https://t.co/iAPOFWW8Rm by @0xGalz#ReversingTips pic.twitter.com/se01IIgMFz
-Reversing Tip 7/30-— Guy🏂 (@whtaguy) April 7, 2020
Reversing is more fun w/symbols. If symbols are stripped, try looking for symbols in older versions, versions for other OSs, beta builds, and the mobile app versions.
If still no symbols, check which has the most debug prints#BinReversingTips pic.twitter.com/HpoH0U9PBv
-Reversing Tip 8/30-— Guy🏂 (@whtaguy) April 8, 2020
Want a faster way to open IDA on your exe? 1) open Explorer 2) enter “sendto” in the path bar 3) drag an IDA Pro shortcut to this folder 4) You can now right-click “send to IDA” on any file 5) ? 6) PROFIT!#BinReversingTips pic.twitter.com/9rQI1gD53y
Bonus: works for other programs too!— Guy🏂 (@whtaguy) April 8, 2020
Drag shortcuts to your top tools into that folder, and they will be available through the “send to” menu
-Reversing Tip 9/30-— Guy🏂 (@whtaguy) April 9, 2020
Search https://t.co/vwhdP466Aa to name any unknown Windows constant/guid/error code you come across while reversing#BinReversingTips pic.twitter.com/5OaUfg3iFP
-Reversing Tip 10/30-— Guy🏂 (@whtaguy) April 10, 2020
Pimp your gdb experience with ‘layout asm’ & ‘ layout regs’, or take it a step further by installing pwndbg https://t.co/VGBuHf3QNK #BinReversingTips pic.twitter.com/VtMh6bh4rO
-Reversing Tip 11/30-— Guy🏂 (@whtaguy) April 11, 2020
Want to reverse code handling a GUI window?
Find the window’s Resource ID with ResourceHacker, then search IDA for where that ID is used (alt+I to search). I used 7zip In the example belowhttps://t.co/6lZJnLJhnh #BinReversingTips pic.twitter.com/9rrpv7Fd14
-Reversing Tip 12/30-— Guy🏂 (@whtaguy) April 12, 2020
Get the best from both static & dynamic analysis by sync’ing your debugger (WinDbg/GDB/x64dbg/ and more) with your disassembler (IDA/Ghidra) through Ret-Sync https://t.co/DhOWYZUT67 #BinReversingTips pic.twitter.com/3Da9tZzfHW
-Reversing Tip 13/30-— Guy🏂 (@whtaguy) April 13, 2020
Optimized magic numbers can uncover functionality. Examples: 0x7efefeff is used in strlen, and 0x5f3759df is used to find the inverse square root (1/sqrt(x))
more info: https://t.co/nRrpl46g8w , https://t.co/Jb4UIn77Ue#BinReversingTips pic.twitter.com/yFEgbaoSmj
as the numbers appear in source: pic.twitter.com/PunrTtHWQD— Guy🏂 (@whtaguy) April 13, 2020
-Reversing Tip 14/30-— Guy🏂 (@whtaguy) April 14, 2020
Multiplying by a constant followed by +’ing then shifting(>>) can be a sign of optimized ÷
Example: ×’ing by 0x92492493 is the first step in efficiently dividing by 7. More info: https://t.co/7QsRtLl3LN#BinReversingTips pic.twitter.com/uLaugZsM5F
-Reversing Tip 15/30-— Guy🏂 (@whtaguy) April 15, 2020
In IDA's disassembler, you can use the numpad +/- keys to change the number of args passed to a function w/variable arguments such as printf #BinReversingTips #idaTips pic.twitter.com/ob09sRtPF7
-Reversing Tip 16/30-— Guy🏂 (@whtaguy) April 16, 2020
controlling input & running a function we're reversing is super useful. You can do this by "converting" the func’s exe → dll, and then invoke the func like a dll func. Explanatory blog post I wrote: https://t.co/B00BfzVicQ#BinReversingTips pic.twitter.com/o0BsCXWUuc
-Reversing Tip 17/30-— Guy🏂 (@whtaguy) April 17, 2020
Extracted embedded firmware but don’t know its base addr to give IDA?
Use string ptrs: use a script such as https://t.co/inqA2Q4lRQ to find which base addr aligns the most ptrs to valid strings#BinReversingTips pic.twitter.com/SsBF7JXV9O
And the linked code is written in Rustlang, a treat for all you rust lovers ;) <3— Guy🏂 (@whtaguy) April 17, 2020
-Reversing Tip 18/30-— Guy🏂 (@whtaguy) April 18, 2020
Building on the last tip, another way to find a fw’s base addr is using absolute calls:
Find which base addr results in the most calls “landing” on beginnings of functions (code init’ing the frame pointer & allocating stack vars)#BinReversingTips pic.twitter.com/PSpeUE04vs
-Reversing Tip 19/30-— Guy🏂 (@whtaguy) April 19, 2020
found a bunch of strings, but no xref to their use? You probably found a str array: the strs are accessed w/an offset from the 1st str (array base), which _will_ have an xref#BinReversingTips pic.twitter.com/bFDqMLMmDp
Code above is from Nvidia’s NvCamera64.dll. Specifically in this example, I found an array of structs in the form <ErrorCode, ErrorString, ErrorDescription> (it’s not a _pure_ string table)— Guy🏂 (@whtaguy) April 19, 2020
Also, the ErrorCode field is redundant as it can be determined from the struct’s index in the array. Error ID 0 = ErrorTable[0]— Guy🏂 (@whtaguy) April 19, 2020
After creating a struct and defining proper types: pic.twitter.com/qigzUsS9iQ— Guy🏂 (@whtaguy) April 19, 2020
-Reversing Tip 20/30-— Guy🏂 (@whtaguy) April 20, 2020
GDB TIPS EDITION
The ability to break on reading/writing memory is well known, BUT
did you know you can break on a write to a register?!#BinReversingTips //🧵[1/3] pic.twitter.com/8t045rJtxi
GDB TIP— Guy🏂 (@whtaguy) April 20, 2020
Anytime GDB prints $<number>, it is actually creating a new variable you can use:#BinReversingTips // [2/3] pic.twitter.com/26120eUxgO
3 ways to write to memory in GDB (commands in back-ticks):— Guy🏂 (@whtaguy) April 20, 2020
1) use `set`
2) `call` memcpy/strcpy
3) write data from a file to memory with `restore`#BinReversingTips // [3/3] pic.twitter.com/ZJbyrGhRkd
-Reversing Tip 21/30-— Guy🏂 (@whtaguy) April 21, 2020
Trick to help find libc functions: Exploit the xref count
memcpy/strlen will be called often, while strtok for example probably less (tip credit: @brinlyau). What tricks do you have to find unknown libc functions?
-Reversing Tip 22/30-— Guy🏂 (@whtaguy) April 22, 2020
STRING HUNTING EDITION
strs help identify code functionality; how can we find a str seen in the GUI that isn’t in IDA’s strings window? a thread🧵#binReversingTips / [1/5] >>> pic.twitter.com/Tb7NFb31ch
1) the strings window only has auto-identified strings, which misses some.— Guy🏂 (@whtaguy) April 22, 2020
Use ALT-B to search the whole binary, even places not identified as data regions. [2/5] #BinReversingTips pic.twitter.com/AFPiU552oh
2) sometimes the string isn’t embedded in the binary, but is imported from an external resource file. find the str by grepping the program's installation folder [3/5] #BinReversingTips pic.twitter.com/xrYbXnYJqr— Guy🏂 (@whtaguy) April 22, 2020
3) Google the str to see if it’s system generated: error strings for example, can be right from lib functions such as perror()/FormatMessageA(), in which case the str won’t be in the exe [4/5] #BinReversingTips pic.twitter.com/Qlnx19xRVE— Guy🏂 (@whtaguy) April 22, 2020
4) Last resort: Time Travel Debugging. 1) Start debugging the program with TTD 2) when the string appears, scan the program’s memory for its addr. 3) go back in time to find when/where the string was put there [5/5] https://t.co/j3MeOkdDX0 // #BinReversingTips— Guy🏂 (@whtaguy) April 22, 2020
-Reversing Tip 23/30-— Guy🏂 (@whtaguy) April 23, 2020
The easiest way to find the “main()” function is by working in reverse: find which function’s return value (saved in eax) is passed to exit() - that’s main()#BinReversingTips pic.twitter.com/X7NoqN0bMH
-Reversing Tip 24/30-— Guy🏂 (@whtaguy) April 24, 2020
Looking to find code handling certain logic?
Search previous versions’ release notes to find when that logic was last updated. Next, bindiff the version before & of that release, the diff will have your target func https://t.co/2YvMYirXJb / #BinReversingTips pic.twitter.com/TcIH7qnyLg
-Reversing Tip 25/30-— Guy🏂 (@whtaguy) April 25, 2020
Get the best from both IDA’s decompiler & disassembler by overlaying the C code on the ASM in graph view (by clicking the “/” key)#BinReversingTips pic.twitter.com/Yxrrdh9UnF
-Reversing Tip 26/30-— Guy🏂 (@whtaguy) April 26, 2020
Ensure malware you’re researching won’t accidentally run by appending “.dontrunme” to the extension, which will prevent windows from executing the file when it’s double clicked. On linux just `chmod -x`#BinReversingTips #infosec pic.twitter.com/RAIwD8DPDp
-Reversing Tip 27/30-— Guy🏂 (@whtaguy) April 27, 2020
Sometimes you can reverse a function solely by looking at its call graph. The function calls to/from a target reveal a lot about its logic. Let’s analyze some examples: a thread🧵 [1/6] #BinReversingTips pic.twitter.com/yuRCRNOmVG
function sub_4a6c60’s call graph is below. Focus on direct calls (direct arrow from sub_4a6c60 to somewhere else) and make an educated guess about sub_4a6c60’s functionality [2/6] pic.twitter.com/Lv4LUmFHcD— Guy🏂 (@whtaguy) April 27, 2020
Because sub_4a6c60 calls LoadLibraryExW, FindResource, LoadResource, SizeofResource, and FreeLibrary -all funcs related to loading resources- we can (safely) assume sub_4a6c60 handles loading resources. We figured this all out without looking at one line of code! [3/6]— Guy🏂 (@whtaguy) April 27, 2020
Let’s look at another ex: sub_82061A’s call graph is below.— Guy🏂 (@whtaguy) April 27, 2020
notice this func is called from v. many places. This limits the logic this func could have handled since its code must be useful for many other unique funcs. Further analysis shows this is a panic function. [4/6] pic.twitter.com/oejjdqHzLx
The easiest way to view a call graph in IDA is to use the “Proximity Viewer” from the View menu. [5/6] pic.twitter.com/WtSUhF7aeZ— Guy🏂 (@whtaguy) April 27, 2020
What insights have you ever gained from not directly reversing your target function? [6/6]— Guy🏂 (@whtaguy) April 27, 2020
-Reversing Tip 28/30-— Guy🏂 (@whtaguy) April 28, 2020
IDA auto-analysis missed a function arg because it was passed in an “unexpected” register?
Use the “__usercall” call convention with “@<register_name>” to declare args & their location:#BinReversingTips #idaTips pic.twitter.com/utSKuMnFw7
-Reversing Tip 29/30-— Guy🏂 (@whtaguy) April 30, 2020
buckle up buckaroos! Here's the most useful RE strategy no one talks about:
*analyze the block layout before diving into ASM code*. Layout view is available on many disassemblers, here’s how to use it #BinReversingTips Explanatory thread🧵[1/6] >>> pic.twitter.com/fakqvBYKjV
Let’s start with an easy example. The 1st image shows the layout of an “if” statement: the code splits to 2 paths. Question: What layout does the 2nd pic show? Answer on the next tweet. Assembly is purposely hidden - that’s the point of this ;) [2/6] pic.twitter.com/d5G3tsfhcD— Guy🏂 (@whtaguy) April 30, 2020
If you answered it’s a switch case statement, you’re correct :) Great!— Guy🏂 (@whtaguy) April 30, 2020
Let’s use our new killer skillz on func_1. Q: func_1 is most likely:
1. Computing a hash
2. Parsing a format
3. String comparison [tweet 3/6] pic.twitter.com/j9gGiDlcS6
the answer is #2. Func_1 has many “if”s leading to a return block (End A), typical of format parsing code to bail early if it finds a corrupt field/magic value. Here is func_1 fully exposed to confirm our assumption [4/6] pic.twitter.com/cUoYaTq4v0— Guy🏂 (@whtaguy) April 30, 2020
Last example; what is func_2 most likely handling?— Guy🏂 (@whtaguy) April 30, 2020
1. Computing a hash
2. Parsing a format
3. String comparison [tweet 5/6] pic.twitter.com/40A1qf45DQ
The answer is #3. Func_2 has a loop, typical in str related funcs which use the loop to iterate over the str’s chars. Also, we can rule out #2 w/knowledge from the prev. tweet & rule out #1 from my 1st RE tip 😉— Guy🏂 (@whtaguy) April 30, 2020
Func_2 exposed: </END THREAD> pic.twitter.com/vZdERpjCHM
-Reversing Tip 30/30-— Guy🏂 (@whtaguy) May 1, 2020
better than anything technical I can share: RE isn’t a 1337 h4ck3r only reserved field! Like anything else: It’s open to everyone! And like any skill, “just” enjoy it, work hard, and you’ll get it. thread 🧵 #BinReversingTips [1/2]>>>
Easier said than done, but don’t be discouraged when things are hard. I like to think of this @maddiestone story https://t.co/xY2gf3ucxr— Guy🏂 (@whtaguy) May 1, 2020
a "setback" is only a waste if you didn't learn anything from it [2/2] EOF
Leave a comment on this post or tag me on Twitter - I reply pretty quickly :)
Comments
Post a Comment