Created
July 13, 2019 16:48
-
-
Save hc0d3r/318b0aa0ae4697372688b624cecbd610 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <spyderhook.h> | |
#include <ignotum.h> | |
#include <sys/syscall.h> | |
#include <sys/wait.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#define die(msg) do { \ | |
perror(msg); \ | |
exit(1); \ | |
} while(0) | |
// for human-beings | |
enum { | |
pipe_read, | |
pipe_write | |
}; | |
int syscall_enter(pidinfo_t *info, unsigned long nr, void *data); | |
int syscall_result(pidinfo_t *info, unsigned long nr, void *data); | |
void *read_until_zero(pid_t pid, off_t raddr, size_t *len); | |
void hexdump(const char *data, size_t n); | |
void print_execve(pid_t pid); | |
int wantcontinue(void); | |
/* lê a memoria ate encontrar um null-byte | |
* ou ate não ter mais dados que possam ser lidos */ | |
void *read_until_zero(pid_t pid, off_t raddr, size_t *len){ | |
char *buf = NULL, *aux; | |
size_t n = 128, prev = 0, total, i, nread; | |
while(1){ | |
buf = realloc(buf, n); | |
if(buf == NULL) | |
die("realloc()"); | |
aux = buf+prev; | |
total = n-prev; | |
nread = (size_t)ignotum_mem_read(pid, aux, total, raddr+prev); | |
for(i=0; i<nread; i++){ | |
if(aux[i] == 0){ | |
i++; | |
goto end; | |
} | |
} | |
if(nread != total) | |
break; | |
prev = n; | |
n *= 2; | |
} | |
end: | |
*len = prev+i; | |
return buf; | |
} | |
/* don't judge me for be lazy */ | |
void hexdump(const char *data, size_t n){ | |
pid_t pid; | |
int pfd[2]; | |
pipe(pfd); | |
pid = fork(); | |
if(pid == 0){ | |
close(pfd[pipe_write]); | |
dup2(pfd[pipe_read], 0); | |
execlp("hexdump", "hexdump", "-C", NULL); | |
_exit(0); | |
} | |
write(pfd[pipe_write], data, n); | |
close(pfd[pipe_write]); | |
close(pfd[pipe_read]); | |
waitpid(pid, NULL, 0); | |
} | |
void print_execve(pid_t pid){ | |
long exe, args, addr; | |
size_t len; | |
int i = 0; | |
char *string; | |
/* pega os endereços de memória */ | |
exe = sh_getreg(pid, SH_FIRST_ARG); | |
/* read_until_zero usa a libignotum */ | |
string = read_until_zero(pid, exe, &len); | |
printf("\n[*] cmd = %s\n", string); | |
free(string); | |
if(wantcontinue()){ | |
return; | |
} | |
args = sh_getreg(pid, SH_SECOND_ARG); | |
while(1){ | |
addr = 0; | |
/* addr = *remote_argv */ | |
ignotum_mem_read(pid, &addr, sizeof(long), args); | |
if(addr == 0) | |
break; | |
printf("ARG[%d]:\n", i++); | |
/* printf("%s\n", addr); */ | |
string = read_until_zero(pid, addr, &len); | |
hexdump(string, len); | |
free(string); | |
/* remote_argv++ */ | |
args += sizeof(long); | |
} | |
} | |
int wantcontinue(void){ | |
char opt; | |
printf(">> printar os parametros (s/n) ? "); | |
opt = getchar(); | |
while(getchar() != '\n'); | |
return (opt != 's' && opt != 'S'); | |
} | |
int syscall_enter(pidinfo_t *info, unsigned long nr, void *data){ | |
/* faz a lib 'pular' a syscall */ | |
if(nr == SYS_prctl){ | |
return SH_SKIP_SYSCALL; | |
} | |
/* printa os parametros da syscall execve */ | |
if(nr == SYS_execve){ | |
print_execve(info->pid); | |
} | |
return SH_CONTINUE; | |
} | |
int syscall_result(pidinfo_t *info, unsigned long nr, void *data){ | |
if(nr == SYS_ptrace){ | |
/* altera o resultado da syscall ptrace | |
* que no SHC é usada para detectar se | |
* o processo está sendo debugado */ | |
sh_setreg(info->pid, SH_SYSCALL_RESULT, 0); | |
} | |
return SH_CONTINUE; | |
} | |
int main(int argc,char **argv, char **envp){ | |
spyderhook_t *sh; | |
int err; | |
setvbuf(stdout, NULL, _IONBF, 0); | |
if(argc != 2){ | |
printf("unshc [prog]\n"); | |
return 0; | |
} | |
/* re-executa o programa se o primeiro argumento | |
* for diferente de /bin/bash */ | |
if(strcmp(argv[0], "/bin/bash")){ | |
char *exe = argv[0]; | |
argv[0] = "/bin/bash"; | |
execve(exe, argv, envp); | |
/* encerra o programa, se execve falhar */ | |
return 1; | |
} | |
sh = sh_init(); | |
if(sh == NULL){ | |
die("sh_init()"); | |
return 1; | |
} | |
sh_setopt(sh, SHOPT_FILENAME, argv[1]); | |
sh_setopt(sh, SHOPT_ARGV, argv+1); | |
sh_setopt(sh, SHOPT_ENVP, envp); | |
sh_setopt(sh, SHOPT_ENTER_CALLBACK, syscall_enter); | |
sh_setopt(sh, SHOPT_RESULT_CALLBACK, syscall_result); | |
sh_setopt(sh, SHOPT_FOLLOW_ALL, 1); | |
if((err = sh_mainloop(sh)) != SH_SUCCESS){ | |
printf("error => %s\n", sh_strerror(err)); | |
} | |
sh_free(sh); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment