Picking up from where we left off on our last post, let's keep working with the Vivisect GUI and explore some additional functionality.¬† If you followed along from the first part, we've identified our string and if we jump back to the function graph, it might be good for us to add a comment so that we have an easier time tracking our work on the binary.¬† To add a comment, simply highlight the line you with to comment and press the semi-colon key which will let you add a comment to that line.
Once you reload the Vivisect workspace, your changes will take effect.
Similar to adding comments in your code, it's useful to track variables throughout your programs and Vivisect gives us a nice way to rename variables.¬† For now, let's close reverseme.exe.viv and generate a Vivisect workspace for the program you compiled in Part 1, "conditional."¬† Open the workspace and immediately send conditional.main to FuncGraph0.¬† Let's have a look at the code and see what's going on:
.text:0x08048464 ¬† .text:0x08048464¬† FUNC: int cdecl conditional.main( ) [1 XREFS] .text:0x08048464 ¬† .text:0x08048464¬† Stack Variables: .text:0x08048464¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† -20: int local20 .text:0x08048464¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† -44: int local44 .text:0x08048464¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† -48: int local48 .text:0x08048464 ¬† .text:0x08048464¬† 55¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† push ebp .text:0x08048465¬† 89e5¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† mov ebp,esp .text:0x08048467¬† 83e4f0¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† and esp,0xfffffff0 .text:0x0804846a¬† 83ec20¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† sub esp,32 .text:0x0804846d¬† b8a0850408¬†¬†¬†¬†¬†¬† mov eax,loc_080485a0¬†¬†¬† ; .text:0x08048472¬† 890424¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† mov dword [esp + local48],eax .text:0x08048475¬† e8e6feffff¬†¬†¬†¬†¬†¬† call printf_08048360¬†¬†¬† ;printf_08048360() .text:0x0804847a¬† b8b6850408¬†¬†¬†¬†¬†¬† mov eax,loc_080485b6 .text:0x0804847f¬† 8d54241c¬†¬†¬†¬†¬†¬†¬†¬† lea edx,dword [esp + 28] .text:0x08048483¬† 89542404¬†¬†¬†¬†¬†¬†¬†¬† mov dword [esp + local44],edx .text:0x08048487¬† 890424¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† mov dword [esp + local48],eax .text:0x0804848a¬† e811ffffff¬†¬†¬†¬†¬†¬† call __isoc99_scanf_080483a0¬†¬†¬† ;__isoc99_scanf_080483a0() .text:0x0804848f¬† 8b44241c¬†¬†¬†¬†¬†¬†¬†¬† mov eax,dword [esp + local20] .text:0x08048493¬† 83f863¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† cmp eax,99 .text:0x08048496¬† 7f0e¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† jg loc_080484a6
Right off the bat, Vivisect tells us that we have three stack variables, local20, local44, and local48.¬† In looking at the source code, or even if we run the program, it's pretty easy to see what this program does when its executed.
user@ubuntu:~/vivisect_20130901$ ./conditional Please enter your age99 You are pretty young! user@ubuntu:~/vivisect_20130901$
Let's make a few intelligent guesses...¬† So, 0x08048475 is a call to printf() and is responsible for asking us to input our age.¬† A few lines, down at 0x0804848a, we see a call to scanf() which is where we're inputting out age.¬† Immediately after we enter our age, local20 is moved into EAX and them compared to the value of "99" for our first conditional branch.¬† At this point, it's pretty safe to say that local20 is our age, so we can rename this variable which will be applied throughout the code and be visible anywhere that local20 is passed in subsequent functions/code.¬† To name the local variable something more meaningful, place your mouse within the function, and select function > locals > select local, and rename.¬† Once you reload, you should now see your changes applied.
Renamed Local Variable
One thing we haven't touched on yet is the Vivisect console.¬† In the console, typing "help" will show you a list of available commands.
And for additional information, "help <command>" will show extended usage.
Using the console is pretty straight forward, and if you're stuck on something, the epydocs for the project are very helpful.
To demonstrate one of the commands, let's say we want to find a path between two blocks of interest.¬† With small programs like this, it's trivial to find a path at a glance, but Vivisect allows you to find paths automagically using the codepath command.¬† If we want to find a path between our conditional.main entry point and one of the conditional blocks, we can do this with the following command:
> codepath 0x08048496 0x080484c4 Tracking Paths From 0x08048496 to 0x080484c4 Function VA¬†¬† ¬†Block VA¬†¬† ¬†Size¬†¬† ¬†Function Name ============================== 0x08048464¬†¬† ¬†0x08048464¬†¬† ¬†¬† 52¬†¬† ¬†conditional.main 0x08048464¬†¬† ¬†0x080484a6¬†¬† ¬†¬†¬† 9¬†¬† ¬†conditional.main 0x08048464¬†¬† ¬†0x080484bd¬†¬† ¬†¬† 12¬†¬† ¬†conditional.main
Where 0x0904896 is our first address, and 0x080484c4 is the second address.
Lastly, one additional command you may find to be particularly useful is the codediff command which performs a binary diff on two Vivisect workspaces.¬† As an exercise for the reader, change the conditional.c source code in part 1 to have it branch differently depending on the inputted ages and diff the two workspaces once you've compiled your changes!¬† Finally, even for the numerous console commands we didn't cover, be sure to check them out on your own as the Vivisect console provides an unbelievable amount of power that would be impossible to cover in this series.
Next Sunday, we'll wrap up this series with Part 3 where we'll cover working with VDB, the Vivisect debugger.¬† That's all for now, I'm off to watch the season finale of Breaking Bad, and you should be as well!