Showing posts with label binary. Show all posts
Showing posts with label binary. Show all posts

Tuesday, January 27, 2015

Statically linked binaries - Library detector

A program can be compiled dynamically or statically on Linux. For simplicity's sake - I considered only C binaries. When you dynamically compile a program the libraries do not get included into the binary itself - the functions that they export are called at runtime. In a statically linked binary however, all the libraries that the binary needs ... to run... are part of the binary itself. And that if you are reversing something...is a pain. Coz you don't know which part of the code is the binary...and which part is library code. IDA detects a lot - but not all of it... not enough ..for sure. So I decided to try and so something..

This little project came into my mind primarily while playing the reversing challenges in CTFs. The files there used to be massive (4 digit numbers of functions) and very difficult to solve (for me anyway :)). I would never be able to identify which code was library code - in the case of statically linked binaries. Thus I could never complete those challenges OR it took me a lot of time. I still can't complete many but that's a separate story ;)

Anyway TL;DR I wrote a few simple IDAPython/Python scripts that basically compare the IDB of the binary to be reversed and a whole lot of library code. The more idea you have about the exact libraries that were used while building the binary - the more accurate this tool will be.

It is certainly a start to a fairly complex problem IMO and I hope that people more knowledgable than me in this space, can extend this and make it even more useful. At the very very least, I hope it will at least show people what NOT to do while attempting to solve this problem :)

The code I wrote can be found here.

Hopefully over time - I can make this even better or maybe find a better solution to this problem.

Sunday, December 21, 2014

FireEye - FlareOn Challenge 6 Argument 2

So if you read my previous post..you'd know I was stuck on Argument 2 last time. I finally managed to crack it with a little help. The answer had been staring at me all the time and somehow I'd overcomplicated things. Oh well. I learnt a lot.

So..the last time in the previous post, I was stuck at the function 401164. I went through it multiple times, sat and marked blocks out in IDA, used Hexrays on it to get C code (I don't do this until it's an absolute last resort) but all I could see was loads of operations on a big chunk of encrypted text.

Yeah. So I found this chunk of text at 729900..and this is exactly what it looked like.

---------------------------
SIn46AAAAABIixwkSIPDCusKSDHSSDHAsDwPBcAI8oA4G3QC/+NIg8ABgDBAgDDygDCzgDgwdAL/40iDwAGAMHGAOB90Av/jSIPAAYAAo8AIvIA4sHQC/+NIg8ABgCh5gDjodAL/40iDwAHACIKAKCiAOPZ0Av/jSIPAAYAosMAITYAALIA4H3QC/+NIg8ABgABUwACZgDC4wAgqgAA/gDivdAL/40iDwAHACLqAOF10Av/jSIPAAYAw7cAIbIAAMIA4KXQC/+NIg8ABgCi/gDi1dAL/40iDwAHAALyAAIzAAHuAKDGAAGOAOKV0Av/jSIPAAcAAIMAAFoAwrsAAmIA483QC/+NIg8ABwAhugADSgDimdAL/40iDwAGAADSAOGJ0Av/jSIPAAYAAzYAoEIAAYoAwsoA4MnQC/+NIg8ABgDC3gDBzwAgHgDjrdAL/40iDwAGAADSAKGHACDaAAFuAKEyAOAt0Av/jSIPAAYAAWoA4mnQC/+NIg8ABwAiigDiZdAL/40iDwAGAMH6AKOeAOCt0Av/jSIPAAYAouIAwhoAATsAISsAAV4A4r3QC/+NIg8ABwAiGgDDowACVgDBKgDCtgDjDdAL/40iDwAHACEWAMMyAAByAOAN0Av/jSIPAAYAoSoA443QC/+NIg8ABgDClwAiQgDjKdAL/40iDwAHACN7AADaAMHiAKNiAOD50Av/jSIPAAYAAtYAorcAIicAAosAAEYA42HQC/+NIg8ABgABAgCghwAjAgDiCdAL/40iDwAHAAOOAOHt0Av/jSIPAAYAoeMAI9oA413QC/+NIg8ABSDHASDH/SDH2SDHSTTHAagJfagFeagZaailYDwVJicBIMfZNMdJBUsYEJAJmx0QkApoCx0QkBAkeS1ZIieZqEFpBUF9qKlgPBUgx9moDXkj/zmohWA8FdfZIMf9XV15aSL8vL2Jpbi9zaEjB7whXVF9qO1gPBZDr/pA=
------------------------------

The function iterated for the length of this string and performed some operation on it ... using a byte array at 4F4000. But I couldn't understand what it was doing....with all that math. Specially because the very next function, was just an exit function.

Now I'd marked it as an exit function a long time back...and forgotten about it...and not analyzed its code carefully at all. After all, it's exit() ffs... what's there to look into? I was wrong :(

I pinged a person on reddit for a pointer. He/she said I was close...and should think about encoding and the = sign. Sure, I think. Base64. Obviously. But why is that relevant here? Yeah the encrypted text had an = at the end...but so what? It's too big for an Email address. So what's the damn point of decoding it? That's what I'd thought...a long time back.

Anyway I copied the text and threw it into an online Base64 decoder...





and my eyes popped out when I saw what I did.









Look at the screenshot...the right pane..towards the bottom. You'll see some ASCII text called /bin/sh. It's trying to call a shell.... it's shell code. And I'd been staring at it for at least 2-3 days. #-o. Serves me right for assuming things. Sigh.

Anyway, if there's shell code, that means the program is going to jump to it at some point. And I think...wtf.... all that's left is that exit() call at 44bb2b. When the hell is it jumping? And where's that code?

So I then decide to separately throw the shellcode into a disassembler and analyze it. Since it didn't have the ELF header and I was in no mood to recreate one (if I could :D) I threw the code into an awesome online disassembler at http://www2.onlinedisassembler.com/.













...and the code there looked very very familiar. I'd seen it somewhere. Where? Then it hit me...it was IN the exit function.

The exit function had code that compared something with '1b' at the offset cfc4... and exit if it didn't match. And what was it comparing it with? The 2nd argument. And if you didn't enter that correctly..which I wasn't...it'd fail.

So at this point...it was just about reversing the algorithm inside. Here I have a confession to make. While searching for hints and verifying the 1st argument, I'd accidentally seen part of the 2nd argument on one of the solutions, so I knew it started with lin. That sucked. But anyway... just to verify I entered 'l' and..yes..it passed the jump. So the I just needed to solve that entire algorithm...which was just different basic math at every step. Rotate right an left, xor, add, and sub..with binary and hex. I started doing it manually...but was just horribly bored as the pace was very slow guessing it.

So I decided I'd write code for it and solve it. It's basically mind numbing work predicting character by character...and the algorithm is different each time. An utter waste of time really... and this made no sense to me from FireEye's perspective. Oh well I guess that's how real malware is :shrug

Here's the code I wrote - it's just a very quickly written piece of code. Not great at all. But it works:

https://gist.github.com/arvinddoraiswamy/846de119b09dcbb8ea92

I wrote code till the "@" character...and then just guessed the rest. Here too...out of sheer tedium...I guessed 1 character...manually added it to my flag..and then proceeded to solve the algorithm again for the same character. And wondered wtf was wrong now...and why gdb kept throwing me out.

Only googling the exact answer showed me the error of my ways :|. Obviously, that's not how it works in real life...but really I was done...and there was nothing left to solve in the challenge, so I think it was ok.

The final flag was:- l1nhax.hurt.u5.a1l@flare-on.com

Oh you bet. This was a painful painful challenge. What an utter load of junk there was inside. 7 or 8 functions out of some 2700+ that were useful. Sheesh :)

p.s..The bad thing was that someone had written the flag of challenge 7 underneath challenge 6... :( but luckily I have already forgotten it :D. I won't solve challenge 7 for a few days till I am sure I don't remember anything.