Thomas Gruber
Thomas Gruber

Reputation: 63

How to change argv[0] from outside?

I have a C code like this:

#include <stdio.h>

void x(int argc, char** argv) {
  printf(argv[0]);
}

int main(int argc, char** argv) {
  char* secret = "SECRET";

  if (argc < 2)
    x(argc, argv);
}

I now want to do a format string attack to print the secret to the shell. However, I don't know how get the string that I want to argv[0] and how I would access data from another scope (because from x it's not possible to directly address the pointer secret.

How would I do that?

Upvotes: 1

Views: 6296

Answers (2)

melpomene
melpomene

Reputation: 85787

In unix, programs are started with execve (or one of its wrappers, such as execlp). All exec* functions let you pass arbitrary strings for argv, including argv[0].

If you're doing this interactively from a shell, have a look at the exec builtin:

( exec -a '%x...' ./prog )

The parens create a subshell, exec loads and runs ./prog into the subshell process, and the argument to -a is used as argv[0].

As for how you can access variables, look at the generated assembler code. If secret is stored on the stack and printf pulls arguments from the stack, it may be possible to get the results you want just by specifying enough %x directives (followed by %s).

Upvotes: 15

cadaniluk
cadaniluk

Reputation: 15229

argv[0] contains the program name, which is usually the string you invoke the program with. For a program executed with ./a.out, argv[0] would point to ./a.out.

Your format string attack would need to modify argv[0]. That means you need to rename the executable to a format string that fits your needs.

I changed your program to read from argv[1] and removed the argc < 2 restriction. I used %s and prepended %d until "SECRET" was printed. Why %d? I figured the stack is aligned to a multiple of int (which %d prints) because sizeof(int) is usually the natural word size.

In the end, I came up with %d%d%d%d%d%d%d%d%d%d%d%d%s. This prints some values from the stack (if there was some kind of "skipping" formatter to avoid actually printing those values, I'd use it), pops those, and prints "SECRET" in the end.

Note that this is undefined behavior and completely dependent on your machine, though.

Upvotes: 2

Related Questions