Giter Club home page Giter Club logo

Comments (2)

 avatar commented on July 28, 2024

Seems like it's a revsh bug when running on older systems

from mimic.

emptymonkey avatar emptymonkey commented on July 28, 2024

The "Searching for main()..." bug is less of a bug and more of a design flaw. (Due to my own lack of understanding on how this probably should work.) Let me give a bit of background on mimic's internals and I think this will become clear.

The identity of a process is kept in two spots that are reflected in /proc/PID/ and are thus referenced by outside programs like ps. The first spot I think is in kernel memory. This is reflected in /proc/PID/stat. Any process can change this through the prctl()'s PR_SET_NAME function. The second place is the argv[0] memory at the base of the stack inside the process itself. If you do:

memset(argv[0], '\0', strlen(argv[0]));
memcpy(argv[0], "foo\0", 4);

Your process is now named foo and a "ps aux" will display it as such. This is reflected in /proc/PID/cmdline which is a window directly into the stack of the process itself.

Performing both the argv overwrite as well as the prctl() call results in what I call the "mimic maneuver", and any process can do it to itself. The purpose behind the mimic program was to solve the general problem and give a user the ability to run any program and have the new program perform these actions (through the magic of ptrace). The ptrace() to call prctl() is easy. The harder problem is the overwriting of argv[0]. It's easy to overwrite it, but then that information is lost to the program you are genuinely trying to run that isn't aware of the mimic maneuver it is itself performing.

My approach to solving this was to have mimic perform the following steps against the new process:

  • execve() the new process with the fake (mimic'd) arguments already in argv / envp.
  • hook the new program, thus landing at execution start (not main()).
  • use ptrace to mmap() a chunk of anonymous private memory that will house the legitimate argv / envp that the real program needs to run, and copy those arguments into this new memory space.
  • single step through the process until we find main().
  • change the pointer for argv and envp here at the start of main to point to our new mmap'd memory section that holds the legitmate args / envs.
  • release the program and let it run normally.

So you see, I have a "heuristic" to determine that we have found main, and honestly, it kind of sucks. (Yes those are meant as "air quotes" because here by heuristic I really mean "wild ass guess".) It seems to work almost all of the time, so I've left it mostly alone. Honestly, I'm not thrilled with the heuristic approach to solving this, but I'm not sure how to find main() in a more reasonable and stable method. If the heuristic doesn't land on a particular run, then you are literally left single stepping via ptrace() through the entire program as it runs. Very sub-optimal. For reference, here is the line of code that represents that heuristic:

	while( ! \
			( \
				(test_regs.rdi == argc_stack_val) && \
				(test_regs.rsi == argv_stack_val) && \
				(test_regs.rdx == envp_stack_val) && \
				(test_regs.rip > child->map_head->start_address) && \
				(test_regs.rip <  child->map_head->end_address) && \
				(test_regs.rax == test_regs.rip)
			)){

As you can see, it's all cpu register state inspection. And the heuristic is tuned to the runs I've done on my machine, so it's going to be weighted toward glibc. Probably wouldn't hold up across notable internal changes to glibc. Almost certainly wouldn't hold up when used against a binary that uses a different libc.

So yes, "searching for main()" bugs. Totally a thing. Less bug and more "developer doesn't know what the hell he's doing." :)

from mimic.

Related Issues (4)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.