1

Apologies if this account question may sound a bit stupid but I really need help with something

Let's say I had a function that looks something like this :

#undef curl_easy_setopt
CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
{
  va_list arg;
  CURLcode result;

  if(!data)
    return CURLE_BAD_FUNCTION_ARGUMENT;

  va_start(arg, tag);

  result = Curl_vsetopt(data, tag, arg);

  va_end(arg);
  return result;
}

How could I go about the proccess of finding this function in IDA?

0

2 Answers 2

3

As it happens, I recently reverse engineered (and published an analysis of) a program that uses Curl, and I had the IDB open in the background. I decided to see if I could find the function in question. Here's how I did it.

  1. First, by searching for CURLE_BAD_FUNCTION_ARGUMENT, we determine that the value of the numeric constant is 43.
  2. Under Search->Immediate value, input the number 43.

enter image description here

  1. IDA then displays a list of locations in the binary that use the immediate constant 43:

enter image description here

  1. Although there are 189 results in the code section, I didn't need to look at all of them. For example, in the second line of the image above, the value is being compared with an 8-bit register; I'm assuming CURLcode is an integer, so that's not the one we want. In the bottom three lines, we can see that one single function contains the constant three (actually, many) times; your snippet shows the number one single time, so that's not the one we want. I exclude many of the possibilities with reasoning like this; anything that is not mov eax, 2Bh, or anywhere that instruction appears more than once in a single function, is placed on the backburner for later analysis (if necessary).

  2. I briefly look at each good-looking result to see if it has a similar control flow shape to the one from your question. Quickly, I find one that looks right (and as it happens, IDA had already named the function curl_easy_setopt due to its Lumina renaming feature):

enter image description here

Note that this trick would not have worked very well if the numeric value of CURLE_BAD_FUNCTION_ARGUMENT had been something like 1, 2, 4, 8, 16, 32, etc. I exploited the fact that the number 43 does not appear extremely often in most programs in order to narrow down my search.

5
  • Thanks for this answer . Just a small question because I'm a bit new to this stuff. How do you search for CURLE_BAD_FUNCTION_ARGUMENT
    – CoolNite
    Mar 11 at 21:01
  • In my example above, I just searched for it on Google. In general, given that your question was about a piece of open-source software, I'd go to the source code and find the enumeration or definition for that name, and determine its numeric value that way. Mar 11 at 22:58
  • What if when I try looking for the value 43 , I can't find anything that resembles what I'm looking for it At all And I did check in the source and I am certain I am supposed to be searching for 43
    – CoolNite
    Mar 12 at 20:22
  • Maybe it's not in there -- either because the program is not using Curl at all, or it's not using that function (or anything that calls that function). Or maybe the function has been inlined, and the return value was deleted because the compiler was able to prove that that return path could never be taken. It might be a good idea to see if you can find either functions that call the one you want, or functions that are called by the one you want -- maybe there are strings in those functions? -- and find yours via cross-references. Mar 12 at 20:39
  • Idk if I can find any function that calls curl_easy_setopt
    – CoolNite
    Mar 12 at 21:22
3

Not a stupid question at all. Even the most seasoned reverse engineers run into issues with this task under sub optimal conditions. Like many challenges in this dark art, the solution, or strategies are "reversed" from conventional problem solving. Very poor attempt at humor... This is what happens to you 30 years later when you've been staring at a 8gb idb of anti-* for two sunsets, as a hobby.

So... You're probably thinking: If there were some strings or easily identifiable numbers I could search for them, and get a cross-reference to the code I'm searching for. That would be nice wouldn't it.

In reality the various metadata is often optimized or obfuscated in the targets of your analysis. Much later you'll cry tears of joy when you find a pdb sitting next to a large heavily obfuscated cpp executable.

Old man tip: Massive malware analysis repos, e.g. VirusTotal, allow you to do some interesting searches. You could for example do a search for: The string Release\TargetApp64.pdb, Signer:"TargetVendor", File version:1.2.x. While malware analysis sites specifically do not directly support the uploading of pdb files due to the obvious disclosure risks, they do however maintain the compressed archive where the TargetExe.exe originated, which usually is where the pdb would also be located. ;)

Without strings and easily identifiable constants you have a wide variety of other characteristics you can pursue and that often will be even more effective in locating what it is you seek.

Constants

If the routine you are examining incorporates a little mathmatics the compiler will optimize the algorithmic code written by the developer into reduced expressions using specific, optimized constant values and data structures. There are quite a few good papers and tools out there now on this topic. You could go after a few PHD(s) and spend a few years studying them write a plugin that will be not run on the next version of IDA or do what I do: Find a genuine subject matter expert in that field that has already done and use their wares, or bribe them with copious amounts of booze, and/or money and high octane life experiences. Everyone wins. Every reverse engineer needs a bad ass math ninja in their corner, especially one with a little swagger and grit. They do exist, and good luck on that. Seriously, bring me the five most brilliant mathematicians and I'll show you a dinner tab that isn't getting paid because they're arguing for an hour over how much each one should pay. Hire the one that pays the whole bill and slow walks to the bar. For now a nice gentleman has been carrying the torch on the original Sigsrch/signsrch/Signsrch: https://github.com/ajkhoury/IDA_Signsrch-7.0

Machine Code Signatures

Machine code and data themselves area a great resource for applying a signature solution. An offset value from a register is can be a characteristic of the size of data structure or the location of a member within that data structure. The larger and more complex the structure or class, the easier it is to identify as the signature can be further enhanced. There are a lot of variations to this but I'm sure you get the idea. For this strategy I'd suggest three things:

  1. Lightweight Wildcard Lib

    Integrate a lightweight popular third party signature solution into your project that is used by people to solve the exact problem you're faced with. Game hackers have to solve this constantly to get their offsets for routines they need to hook and data that they need to manipulate. Check out something like this: https://github.com/wanttobeno/x64_AOB_Search/blob/master/AobScan/Demo.cpp

  2. F.L.I.R.T.

    Ilfak's and team provided a solid framework to tackle this a while ago and it's been one of my key tools ever since. I crawl repos for popular libraries and SDK's then I generate signatures for theroutines. Crypto, netcode, Compression/Algorithmic, runtimes,even focused components like ML engines, sandboxes and crashhandlers. You have to tune it a little bit and defniitely avoid making signatures for routines that are only a few instructions in size, you'll wreck a good workspace with ambiguous symbols.

  3. Ignore Him

    Ignore the person that replies to this thread and suggests an alternative.

    If Mr. Miyagi could read machine code in a few thousand different architectures he might be able to paint Ilfak's fence. I've had Ilfak's tools in my kit before cybersecurity was even a word and Hackers was a hipster movie trying to be like Sneakers that wanted to group into Wargames.

Relationships, Cross References and RTTI

C++ is a real pain when you first encounter it and will be for a while down the road. If you want to get of the curve and do something I should've done the first few years into my career. C/C++ ABI: Think of it as a basic set of guidelines that OS and compiler vendors try to adhere to for the benefit of compatibility. The benefit to us is its one of the few sources of insight into how object oriented languages are consumed and laid out in memory. From a brief search I found this.: https://www.oracle.com/technical-resources/articles/it-infrastructure/stable-cplusplus-abi.html

If any other readers have a link to a modern introduction and overview of the primary ABI(s), it would surely be appreciated here as a reference.

Class Informer (IDA Plugin)

https://sourceforge.net/projects/classinformer/

While IDA does have support for parsing RTTI structures to annotate c++ classes this plugin's last update took it up a notch and it does a great job analyzing virtual tables like those used by C++ classes.

Devirtualize

https://github.com/ALSchwalm/devirtualize

A few years back I stumbled on this IDA plugin, well written, lightweight and relatively easy to customize if needed:

I'd recommend installing it and debug step through it to get an idea how the author detects c++ classes and builds the relationships of its members to something useful in IDA. Then, if you want to really dig in, take on optimizing the code to detect things and solve problems that the original developer did not. Everybody see's things differently, that's the reason that for over 25 years now, there have been dozens of remote root vulnerabilities found in the exact same hundred lines of Sendmail code, a single routine that countless auditors have reviewed previously.

Symbol Porting

If you have partial source code that was compiled into your analysis target you can build an executable or library with symbols, then port those over using something like BinDiff. Over several major version those guys have greatly simplified an otherwise very challenging and tedious task. The best part is they decided to release it as a free to download product now.

BinDiff https://www.zynamics.com/software.html

I'd recommend using whatever tools you have at your disposal to identify the OS version (major/minor), architecture, compiler version, and run time version (e.g. msvcrtX) on your analysis target. Then replicate those as closely as possible in the environment you are building your code with symbols. If the code your are porting symbols for is almost always integrated as a library (e.g. zlib.lib), rather than source, then you're in luck. Libs will be much better targets due to the reduction of compiler steps that may otherwise produce different target code.

Runtime Analysis

There are a lot of run time solutions that will observe data (e.g. class istance pointers) as it flows through code and use those records to dress up code. There are some interesting and heavy computer science/mathematics areas of study that have attracted some real bright folks into further solving this. In all the data flow, taint analysis, tracing, emulation, and other run time methods I've deployed over the years, I find myself doing it statically by hand now. A little code here and there to automate redundant tasks of course. If the code can be executed without requiring a secret, everything needed to execute it is in there somewhere, or somewhere close by. I'm very likely a masochist when it comes to reverse engineering but I think you have to be if you enjoy spending your life living inside a "black box". If anyone ever gives you grief over a what you feel, is a simple question, they are either very young, or very talent less and will never truly shine. The most awe-striking, brilliant people I've had the pleasure to work with were always wide-eyed and exponentially humble. They'd drop everything, miss a critical deadline just to transfer knowledge, learn something themselves, share the experience and tackle an old demon once again. If it wasn't for them this reply wouldn't have been remotely possible.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.