Hola, como en un post anterior (Assmbler inline + Ofuscacion (http://www.underc0de.org/foro/index.php?topic=4846.0)) mio parece que no se entendio el concepto les dejo un mini howto poc xD, a ver si les sirve para algo aun que sea para investigar mas. como no entrare en detalle por falta de tiempo ademas estoy escribiendo en el trabajo.
Ofuscacion: La ofuscación se refiere a encubrir el significado de una comunicación haciéndola más confusa y complicada de interpretar. Wiki (http://es.wikipedia.org/wiki/Ofuscaci%C3%B3n)
Criptografia: La criptografía (del griego κρύπτω krypto, «oculto», y γράφω graphos, «escribir», literalmente «escritura oculta») es la técnica, bien sea aplicada al arte o la ciencia, que altera las representaciones lingüísticas de un mensaje. Wiki (http://es.wikipedia.org/wiki/Criptografia)
Para comprender completamente este documento deberan leer sobre asm basico, syscall's y manejar C a bajo nivel tanto asi como estructuras, manejo de memoria dinamica y punteros.
basta de charla y vamos a la accion.
tenemos el siguiente codigo fuente el cual imprime un texto.
normal.c
#include <stdio.h>
int main()
{
printf("Codigo Normal\n");
return 0;
}
Lo compilaremos sin optimizacion + gdb
ksha@warbof:~/dev/c/ofus$ gcc -ggdb -O0 -o normal normal.c
ksha@warbof:~/dev/c/ofus$ ./normal
Codigo Normal
ksha@warbof:~/dev/c/ofus$
codigo disas
080483c4 <main>:
#include <stdio.h>
int main()
{
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 e4 f0 and $0xfffffff0,%esp
80483ca: 83 ec 10 sub $0x10,%esp
printf("Codigo Normal\n");
80483cd: c7 04 24 a0 84 04 08 movl $0x80484a0,(%esp)
80483d4: e8 1f ff ff ff call 80482f8 <puts@plt>
return 0;
80483d9: b8 00 00 00 00 mov $0x0,%eax
}
80483de: c9 leave
80483df: c3 ret
si analizamos el binario simplemente nos mostraria la informacion del printf o cadena depende del caso y que uso se le de.
ksha@warbof:~/dev/c/ofus$ strings normal
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
puts
__libc_start_main
GLIBC_2.0
PTRh
[^_]
Codigo Normal
ksha@warbof:~/dev/c/ofus$
si por ejemplo ponen cadenas con los procesos Av mas comunes seran detectados rapidamente.
veamos el primer ejemplo de ofuscacion.
NOTA: debes saber C avanzado para enterder algunas lineas del codigo.
ofus1.c
extern int printf(__const char *__restrict __format, ...);
int main()
{
printf("Codigo Normal\n");
return 0;
}
ksha@warbof:~/dev/c/ofus$ gcc -ggdb -O0 -o ofus1 ofus1.c
ksha@warbof:~/dev/c/ofus$ ./ofus1
Codigo Normal
revizando las cadenas ...
ksha@warbof:~/dev/c/ofus$ strings ofus1
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
puts
__libc_start_main
GLIBC_2.0
PTRh
[^_]
Codigo Normal
ksha@warbof:~/dev/c/ofus$
disasm
080483c4 <main>:
int main()
{
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 e4 f0 and $0xfffffff0,%esp
80483ca: 83 ec 10 sub $0x10,%esp
printf("Codigo Normal\n");
80483cd: c7 04 24 a0 84 04 08 movl $0x80484a0,(%esp)
80483d4: e8 1f ff ff ff call 80482f8 <puts@plt>
return 0;
80483d9: b8 00 00 00 00 mov $0x0,%eax
}
80483de: c9 leave
80483df: c3 ret
veamos con el src normal que tal va
normal.c
#include <stdio.h>
char *decrypt( char *str)
{
char *pos = str ;
while( *pos != 0)
{
*pos ^= ( char) 0x0FF ;
pos++ ;
}
return str ;
}
char secret[]={
'C' ^ ( char) 0x0FF,
'o' ^ ( char) 0x0FF,
'd' ^ ( char) 0x0FF,
'i' ^ ( char) 0x0FF,
'g' ^ ( char) 0x0FF,
'o' ^ ( char) 0x0FF,
' ' ^ ( char) 0x0FF,
'N' ^ ( char) 0x0FF,
'o' ^ ( char) 0x0FF,
'r' ^ ( char) 0x0FF,
'm' ^ ( char) 0x0FF,
'a' ^ ( char) 0x0FF,
'l' ^ ( char) 0x0FF,
0
} ;
int main()
{
printf("%s\n",decrypt(secret));
return 0;
}
ksha@warbof:~/dev/c/ofus$ gcc -ggdb -O0 -o normal2 normal2.c
ksha@warbof:~/dev/c/ofus$ ./normal2
Codigo Normal
ksha@warbof:~/dev/c/ofus$ strings normal2
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
puts
__libc_start_main
GLIBC_2.0
PTRh
[^_]
aplicando el XOR 0x0FF cambia drasticamente ya q ahora no vemos cadenas.
080483c4 <decrypt>:
#include <stdio.h>
char *decrypt( char *str)
{
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 ec 10 sub $0x10,%esp
char *pos = str ;
80483ca: 8b 45 08 mov 0x8(%ebp),%eax
80483cd: 89 45 fc mov %eax,-0x4(%ebp)
while( *pos != 0)
80483d0: eb 13 jmp 80483e5 <decrypt+0x21>
{
*pos ^= ( char) 0x0FF ;
80483d2: 8b 45 fc mov -0x4(%ebp),%eax
80483d5: 0f b6 00 movzbl (%eax),%eax
80483d8: 89 c2 mov %eax,%edx
80483da: f7 d2 not %edx
80483dc: 8b 45 fc mov -0x4(%ebp),%eax
80483df: 88 10 mov %dl,(%eax)
pos++ ;
80483e1: 83 45 fc 01 addl $0x1,-0x4(%ebp)
char *decrypt( char *str)
{
char *pos = str ;
while( *pos != 0)
80483e5: 8b 45 fc mov -0x4(%ebp),%eax
80483e8: 0f b6 00 movzbl (%eax),%eax
80483eb: 84 c0 test %al,%al
80483ed: 75 e3 jne 80483d2 <decrypt+0xe>
{
*pos ^= ( char) 0x0FF ;
pos++ ;
}
return str ;
80483ef: 8b 45 08 mov 0x8(%ebp),%eax
}
80483f2: c9 leave
80483f3: c3 ret
080483f4 <main>:
'l' ^ ( char) 0x0FF,
0
} ;
int main()
{
80483f4: 55 push %ebp
80483f5: 89 e5 mov %esp,%ebp
80483f7: 83 e4 f0 and $0xfffffff0,%esp
80483fa: 83 ec 10 sub $0x10,%esp
printf("%s\n",decrypt(secret));
80483fd: c7 04 24 ec 95 04 08 movl $0x80495ec,(%esp)
8048404: e8 bb ff ff ff call 80483c4 <decrypt>
8048409: 89 04 24 mov %eax,(%esp)
804840c: e8 e7 fe ff ff call 80482f8 <puts@plt>
return 0;
8048411: b8 00 00 00 00 mov $0x0,%eax
}
8048416: c9 leave
8048417: c3 ret
8048418: 90 nop
8048419: 90 nop
804841a: 90 nop
804841b: 90 nop
804841c: 90 nop
804841d: 90 nop
804841e: 90 nop
804841f: 90 nop
ksha@warbof:~/dev/c/ofus$ gcc -ggdb -O0 -o ofus2 ofus2.c
ksha@warbof:~/dev/c/ofus$ ./ofus2
Codigo Normal
ksha@warbof:~/dev/c/ofus$ strings ofus2
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
puts
__libc_start_main
GLIBC_2.0
PTRh
[^_]
viendo el disasm
080483c4 <decrypt>:
extern int printf(__const char *__restrict __format, ...);
char *decrypt( char *str)
{
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 ec 10 sub $0x10,%esp
char *pos = str ;
80483ca: 8b 45 08 mov 0x8(%ebp),%eax
80483cd: 89 45 fc mov %eax,-0x4(%ebp)
while( *pos != 0)
80483d0: eb 13 jmp 80483e5 <decrypt+0x21>
{
*pos ^= ( char) 0x0FF ;
80483d2: 8b 45 fc mov -0x4(%ebp),%eax
80483d5: 0f b6 00 movzbl (%eax),%eax
80483d8: 89 c2 mov %eax,%edx
80483da: f7 d2 not %edx
80483dc: 8b 45 fc mov -0x4(%ebp),%eax
80483df: 88 10 mov %dl,(%eax)
pos++ ;
80483e1: 83 45 fc 01 addl $0x1,-0x4(%ebp)
char *decrypt( char *str)
{
char *pos = str ;
while( *pos != 0)
80483e5: 8b 45 fc mov -0x4(%ebp),%eax
80483e8: 0f b6 00 movzbl (%eax),%eax
80483eb: 84 c0 test %al,%al
80483ed: 75 e3 jne 80483d2 <decrypt+0xe>
{
*pos ^= ( char) 0x0FF ;
pos++ ;
}
return str ;
80483ef: 8b 45 08 mov 0x8(%ebp),%eax
}
80483f2: c9 leave
80483f3: c3 ret
080483f4 <main>:
'l' ^ ( char) 0x0FF,
0
} ;
int main()
{
80483f4: 55 push %ebp
80483f5: 89 e5 mov %esp,%ebp
80483f7: 83 e4 f0 and $0xfffffff0,%esp
80483fa: 83 ec 10 sub $0x10,%esp
printf("%s\n",decrypt(secret));
80483fd: c7 04 24 ec 95 04 08 movl $0x80495ec,(%esp)
8048404: e8 bb ff ff ff call 80483c4 <decrypt>
8048409: 89 04 24 mov %eax,(%esp)
804840c: e8 e7 fe ff ff call 80482f8 <puts@plt>
return 0;
8048411: b8 00 00 00 00 mov $0x0,%eax
}
8048416: c9 leave
8048417: c3 ret
8048418: 90 nop
8048419: 90 nop
804841a: 90 nop
804841b: 90 nop
804841c: 90 nop
804841d: 90 nop
804841e: 90 nop
804841f: 90 nop
y les dejo el ultimo un poco mas optimizado.
#include <unistd.h>
char *decrypt( char *str)
{
char *pos = str ;
while( *pos != 0)
{
*pos ^= ( char) 0x0FF ;
pos++ ;
}
return str ;
}
char secret[]={
'C' ^ ( char) 0x0FF,
'o' ^ ( char) 0x0FF,
'd' ^ ( char) 0x0FF,
'i' ^ ( char) 0x0FF,
'g' ^ ( char) 0x0FF,
'o' ^ ( char) 0x0FF,
' ' ^ ( char) 0x0FF,
'N' ^ ( char) 0x0FF,
'o' ^ ( char) 0x0FF,
'r' ^ ( char) 0x0FF,
'm' ^ ( char) 0x0FF,
'a' ^ ( char) 0x0FF,
'l' ^ ( char) 0x0FF,
'\n' ^ ( char) 0x0FF,
0
} ;
int main()
{
decrypt(secret);
write(STDOUT_FILENO,&secret,sizeof(secret));
return 0;
}
ksha@warbof:~/dev/c/ofus$ gcc -ggdb -O0 -o ofus3 ofus3.c
ksha@warbof:~/dev/c/ofus$ ./ofus3
Codigo Normal
ksha@warbof:~/dev/c/ofus$ strings ofus3
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
__libc_start_main
write
GLIBC_2.0
PTRh0
[^_]
080483c4 <decrypt>:
#include <unistd.h>
char *decrypt( char *str)
{
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 ec 10 sub $0x10,%esp
char *pos = str ;
80483ca: 8b 45 08 mov 0x8(%ebp),%eax
80483cd: 89 45 fc mov %eax,-0x4(%ebp)
while( *pos != 0)
80483d0: eb 13 jmp 80483e5 <decrypt+0x21>
{
*pos ^= ( char) 0x0FF ;
80483d2: 8b 45 fc mov -0x4(%ebp),%eax
80483d5: 0f b6 00 movzbl (%eax),%eax
80483d8: 89 c2 mov %eax,%edx
80483da: f7 d2 not %edx
80483dc: 8b 45 fc mov -0x4(%ebp),%eax
80483df: 88 10 mov %dl,(%eax)
pos++ ;
80483e1: 83 45 fc 01 addl $0x1,-0x4(%ebp)
char *decrypt( char *str)
{
char *pos = str ;
while( *pos != 0)
80483e5: 8b 45 fc mov -0x4(%ebp),%eax
80483e8: 0f b6 00 movzbl (%eax),%eax
80483eb: 84 c0 test %al,%al
80483ed: 75 e3 jne 80483d2 <decrypt+0xe>
{
*pos ^= ( char) 0x0FF ;
pos++ ;
}
return str ;
80483ef: 8b 45 08 mov 0x8(%ebp),%eax
}
80483f2: c9 leave
80483f3: c3 ret
080483f4 <main>:
'\n' ^ ( char) 0x0FF,
0
} ;
int main()
{
80483f4: 55 push %ebp
80483f5: 89 e5 mov %esp,%ebp
80483f7: 83 e4 f0 and $0xfffffff0,%esp
80483fa: 83 ec 10 sub $0x10,%esp
decrypt(secret);
80483fd: c7 04 24 fc 95 04 08 movl $0x80495fc,(%esp)
8048404: e8 bb ff ff ff call 80483c4 <decrypt>
write(STDOUT_FILENO,&secret,sizeof(secret));
8048409: c7 44 24 08 0f 00 00 movl $0xf,0x8(%esp)
8048410: 00
8048411: c7 44 24 04 fc 95 04 movl $0x80495fc,0x4(%esp)
8048418: 08
8048419: c7 04 24 01 00 00 00 movl $0x1,(%esp)
8048420: e8 c7 fe ff ff call 80482ec <write@plt>
return 0;
8048425: b8 00 00 00 00 mov $0x0,%eax
}
804842a: c9 leave
804842b: c3 ret
804842c: 90 nop
804842d: 90 nop
804842e: 90 nop
804842f: 90 nop
.. continua ..
Debuggeando ?
No lo pondre ya que es demasiado largo y no quiero seguir poniendo mil post para terminar.
lo que si se los dejo como tarea.
Conociendo Gdb (http://www.drk.com.ar/docs/development/conociendo_gdb.php)
Conclusion.
Es factible utilizar ofuscacion en la creacion de malware ?
totalmente, ojala siempre programen de forma ofuscada podria darles mas codigo pero eso va a depender de como preguntes aca las cosas. tampoco quiero darles todo en bandeja de plata.
Y la criptografia ?
Sep, osea mejor aun si quieren inventar un metodo de cifrado propio seria salvaje lo mas probable es que las compañias AV esten hasta cuando analizando, obviamente hay muchachos q superan el cerebro normal y si tu codigo no es lo suficientemente grotesco lo mas probable es que no se demoren mucho en romperlo (Piensen en PS3 como ejemplo).
para generar codigos mas robustos y dificiles de entender podrian agregar funciones voip o nops osea que no hagan nada asi al desamblar el binario final estaran como 10000 años tratando de ver que son esas funciones.
debugueen el normal1 y el ofuscado3 ... bueno y si tienen tiempo para debuggear el resto les serviria para apreciar mejor las diferencias entre uno y otro.
Espero que les guste, y que me den ideas para programar y generar algunos sources mejores en el tiempo.
Respondere solo preguntas y comentarios relacionados a los codigos.
Por favor no pongas las gracias ya que no las necesito y se rellena el thread con basura.
cualquier duda mas especifica la respondo por mail.
[email protected]
Muy bueno el artículo, se nota que sabes programar :P.
Quizas el simple xor sea detectado por F-PROT o similares y tendrán que idear otra encriptación.. jejeje. Ya vi que lo pusistes tu. jeje
salu2!
Habria q pasarles el source por linea de comandos a los av que hay ... jamas he utilizado un av paral inux :S, en algunos servidores que veo el clamav que es para los virus que hay en correo pero nada mas lo bajare y testiare a ver que tal anda.
le aplicai ksha, despùes la practico, cuando tenga el bicho qlo xD