23

Back story: While running a program under strace I notice that '/dev/urandom' is being open'ed. I would like to know where this call is coming from (it is not part of the program itself, it is part of the system).

So, using gdb, I am trying to break (using catch syscall open) program execution when the open call is issued, so I can see a backtrace. The problem is that open is being called alot, like several hundred times so I can't narrow down the specific call that is opening /dev/urandom. How should I go about narrowing down the specific call? Is there a way to filter by arguments, and if so how do I do it for a syscall?

Any advice would be helpful -- maybe I am going about this all wrong.

1
  • 4
    You may simply do: break open if strcmp($rdi,"/dev/urandom") == 0 Commented Dec 30, 2012 at 3:06

4 Answers 4

15

GDB is a pretty powerful tool, but has a bit of a learning curve.

Basically, you want to set up a conditional breakpoint.

First use the -i flag to strace or objdump -d to find the address of the open function or more realistically something in the chain of getting there, such as in the plt.

set a breakpoint at that address (if you have debug symbols, you can use those instead, omitting the *, but I'm assuming you don't - though you may well have them for library functions if nothing else.

break * 0x080482c8 

Next you need to make it conditional

(Ideally you could compare a string argument to a desired string. I wasn't getting this to work within the first few minutes of trying)

Let's hope we can assume the string is a constant somewhere in the program or one of the libraries it loads. You could look in /proc/pid/maps to get an idea of what is loaded and where, then use grep to verify the string is actually in a file, objdump -s to find it's address, and gdb to verify that you've actually found it in memory by combining the high part of the address from maps with the low part from the file. (EDIT: it's probably easier to use ldd on the executable than look in /proc/pid/maps)

Next you will need to know something about the abi of the platform you are working on, specifically how arguments are passed. I've been working on arm's lately, and that's very nice as the first few arguments just go in registers r0, r1, r2... etc. x86 is a bit less convenient - it seems they go on the stack, ie, *($esp+4), *($esp+8), *($esp+12).

So let's assume we are on an x86, and we want to check that the first argument in esp+4 equals the address we found for the constant we are trying to catch it passing. Only, esp+4 is a pointer to a char pointer. So we need to dereference it for comparison.

cond 1 *(char **)($esp+4)==0x8048514

Then you can type run and hope for the best

If you catch your breakpoint condition, and looking around with info registers and the x command to examine memory seems right, then you can use the return command to percolate back up the call stack until you find something you recognize.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the help! You almost got me there... I have edited my answer with the full process.
Sorry, didn't realize you were on a 64 bit system.
ok, I think I found out: the addresses do not seem to change after process restart and may as well be found out using (gdb) info functions [[regex]]
the address we found for the constant - when did we find the adress? how would one know the adress of the string Hello.txt, not knowing when or where it's initialized? In other words, where did you get your 0x8048514 from?
7

Like Andre Puel said:

break open if strcmp($rdi,"/dev/urandom") == 0

Might do the job.

Comments

5

(Adapted from a question edit)

Following Chris's answer, here is the process that eventually got me what I was looking for:

(I am trying to find what functions are calling the open syscall on "/dev/urandom")

  1. use ldd on executable to find loaded libraries
  2. grep through each lib (shell command) looking for 'urandom'
  3. open library file in hex editor and find address of string
  4. find out how parameters are passed in syscalls (for open, file is first parameter. on x86_64 it is passed in rdi -- your mileage may vary
  5. now we can set the conditional breakpoint: break open if $rdi == _addr_
  6. run program and wait for break to hit
  7. run bt to see backtrace

After all this I find that glib's g_random_int() and g_rand_new() use urandom. Gtk+ and ORBit were calling these functions -- if anybody was curious.

Comments

0

Note that reading from a register gives you the number, i.e., address in this case, stored in the register.

So for the solution by checking $rdi, you'll want to convert $rdi to string before doing string compare, i.e., b open if (int)strcmp((const char*)$rdi, "target") == 0

Moreover, if you somehow cannot determine what the full filename really is, say, it might be a relative path, you may instead use b open if strstr((const char*)$rdi, "part of the filename you can ensure")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.