toizi / ebpf-for-ghidra Goto Github PK
View Code? Open in Web Editor NEWThis project forked from nalen98/ebpf-for-ghidra
eBPF Processor for Ghidra
License: MIT License
This project forked from nalen98/ebpf-for-ghidra
eBPF Processor for Ghidra
License: MIT License
There is no explicit stack pointer for eBPF. Stack access works relative to the R10 register, which serves as the frame pointer for each function and is read-only. It is possible to pass stack addresses as arguments to functions however.
The solana eBPF vm implementation uses a new stack frame with a size of 0x1000 bytes for each function call.
Since the architecture is purely virtual, the return address doesn't get pushed to the stack explicitly like most other architectures do it and the creation of new stack frames is implicit as well.
So ghidra can understand what is going on, I tried emulating these semantics by adding pcode to the call instruction that creates the stack frame for the callee and then saves the return address, as well as popping the frame and the return address in the exit instruction. I also declared this space as used by the callee in the calling convention (localrange). Since R10 for ghidra is denoted as the stack pointer, I believe it is also necessary to declare the stack pointer as growing into the positive direction, since generated code accesses [R10-0x10]
as an example for local stack variables. However this led to weird behavior in the decompiler with huge arrays in the stack, so the stack is currently declared as growing into the negative direction and the stack frame creation is commented out.
Unfortunately the current decompiler output is not great either and even wrong for simple scenarios
The following code's main function compiled with clang test.c --target=bpf -c
int printf(const char *, ...);
int add(int a, int b) {
return a + b;
}
struct SomeData {
int a;
int b;
int c;
int d;
char buf[16];
};
int process_struct(struct SomeData* data) {
data->a = 1;
data->b = 2;
data->c = 3;
data->d = 4;
memcpy(data->buf, "hello", 6);
return 1337;
}
int main(int argc, char **argv) {
int result = add(3, 5);
struct SomeData data = { 0 };
result += process_struct(&data);
printf("%d\n", result);
return result;
}
decompiles to
undefined8 main(void)
{
undefined4 uVar1;
int iVar2;
undefined8 uVar3;
BADSPACEBASE *in_R10;
uVar1 = add(3,5);
uVar3 = *(undefined8 *)((longlong)in_R10 + -0x40);
*(undefined4 *)((longlong)in_R10 + -0x14) = uVar1;
*(undefined8 *)((longlong)in_R10 + -0x20) = uVar3;
*(undefined8 *)((longlong)in_R10 + -0x28) = uVar3;
*(undefined8 *)((longlong)in_R10 + -0x30) = uVar3;
*(undefined8 *)((longlong)in_R10 + -0x38) = uVar3;
*(undefined8 *)((longlong)in_R10 + -0x1000) = 0x100190;
iVar2 = process_struct((undefined *)((longlong)in_R10 + -0x38));
*(int *)((longlong)in_R10 + -0x14) = (int)*(undefined8 *)((longlong)in_R10 + -0x14) + iVar2;
*(undefined8 *)((longlong)in_R10 + -0x1000) = 0x1001c8;
printf("%d\n",*(undefined8 *)((longlong)in_R10 + -0x14));
return *(undefined8 *)((longlong)in_R10 + -0x14);
}
It doesn't catch the zero initialization, probably due to stack reuse from the calls and the in_R10
is problematic as well since it doesn't use regular stack variables.
Additionally it almost always shows the pushing of the return address in the decompilation.
Hi,
I tried to compile the code but got the following error:
/Users/test/ghidra/ghidra_extention/solana_ghidra/eBPF-for-Ghidra/src/main/java/ghidra/app/util/pcodeInject/InjectPayloadEBPFPrologue.java:36: error: InjectPayloadEBPFPrologue is not abstract and does not override abstract method encode(Encoder) in InjectPayload
public class InjectPayloadEBPFPrologue implements InjectPayload {
^
1 error
Here, the InjectPayload
doesn't have the abstract method encode(Encoder)
so I don't know why I am getting this weird error message.
I tried to compile the extension with different versions combination of ghidra
and java
but all resulted in failures. I wonder what version of ghidra, java, and gradle should I try to compile this extension successfully.
my environment:
gradle --version
------------------------------------------------------------
Gradle 8.0.2
------------------------------------------------------------
Build time: 2023-03-03 16:41:37 UTC
Revision: 7d6581558e226a580d91d399f7dfb9e3095c2b1d
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.