yrp604 / rappel

A linux-based assembly REPL for x86, amd64, armv7, and armv8
Other
1.16k stars 55 forks source link

ring-0 mode? #15

Closed thatreguy closed 5 years ago

thatreguy commented 5 years ago

Hi, I think init_module[1] and finit_module[1] could help us run in ring 0 mode. Would it be too hard to implement? Thoughts? Use case could be anything involving quickly hacking and prototyping stuff in kernel mode.

Ref:

  1. http://man7.org/linux/man-pages/man2/init_module.2.html
disconnect3d commented 5 years ago

Would it be too hard to implement?

It's always a matter of "what is hard" ;).

Can you provide some use cases what exactly would you like to try out in the kernel mode?

Note that there are two different contexts in Linux kernel (at least I am aware of those two, there might be more): interrupt context and user context. Which one would you like to be in? Also, the user would have access to all kernel memory and would need to be careful not to break stuff.

Regarding the implementation in Rappel, from the project README:

Rappel is a pretty janky assembly REPL. It works by creating a shell ELF, starting it under ptrace, then continiously rewriting/running the .text section, while showing the register states. (...)

There is no ptrace on the kernel side. One way to implement ring-0 mode would be to create a kernel module that would create a /dev/rappel device that would have the following ioctl requests:

Then Rappel would be a user-space application, a client that would load the Kernel module (requiring root access or better a CAP_SYS_MODULE capability) or requiring it to be already loaded, and then talk to the device to achieve REPL-like functionality.

Also the question is if it is possible to "easily" plug "another mode" to Rappel and if @yrp604 would be interested in such mode in this project.

Also note that ioctl is just one way to have a connection between user and kernel space. There are certainly other ways to achieve the same thing here.

yrp604 commented 5 years ago

Yeah, what @disconnect3d said is spot on. I see a few specific issues:

If you’re interested in doing something like this, I’d look at the bochs debugger as a starting spot, or maybe gdb attached to qemu. To my knowledge the only thing that exists currently like this is windows local kernel debugger, which you could also look at for something similar.

mokomull commented 5 years ago

I actually have a branch I'd been working on that uses KVM instead of ptrace, but unfortunately I also did the work on top of a mostly-working-with-some-caveats branch that uses the LLVM MC assembler: https://github.com/mokomull/rappel/tree/kvm-devel.

There are definitely some known issues in KVM-mode since you can do things like set the page tables to an invalid pointer and leave the host process in an infinite loop trying to look them up. My development mostly stalled when I hit the need for a hashtable to write some helpers to manage page tables for me, but feel free to try it out and file issues against me if you like it.

yrp604 commented 5 years ago

That's super cool! I've fiddled around with the Windows Hypervisor Platform (roughly analogous to KVM) enough to make something similar, but stopped short of putting a REPL around it. I'm somewhat torn if it's a good idea or not -- it would be really, really easy to brick the guest, and you wouldn't get a ton of diagnostic information out as to why things were bricked. For this reason I think emulators make a bit more sense as a foundation for a REPL. On the other hand, something similar to pipe mode could be really interesting: load this ELF as an OS in the newly created guest and give me the register and memory contents when it traps out.

Anyways, in the process there I created some page table creation tools (i.e. generate a page table from a hash table). It doesn't allow updating (you'd have to unmap and regenerate the entire PT) and it's all written in rust, but I'm happy to share the code if you're interested.