jueves, 15 de octubre de 2009

Nuevo differ - TurboDiff

Hola a todos!,

hoy queria comentarles un poco acerca de un nueo differ que se ha publicado en la internet :P

Se trata de un nuevo differ (un programa para comparar .exe, .dll, etc en busca de diferencias) escrito por Nicolas Economou (CORE Security Technologies) y presentado en la Ekoparty 2009 en Argentina.

Basicamente, la mayor diferencia con el resto de los differs actuales (Bindiff, Patchdiff, DarumGrim) es que este differ esta pensado para la busqueda de vulnerabilidades, esta especialmente pensado y programado para que no se le pase el mas minimo detalle a la hora de identificar un minimo cambio como un JA por un JB, cosa que al resto de los differs suele pasarsele por alto en ocasiones, incluso detecta diferencias en funciones que no son analizadas correctamente por IDA (si, me falto decir que es un plugin de IDA :).

Yo lo he utilizado un poco y me parecio bastante mejor que bindiff, el unico punto debil son los graficos puesto que no se comparan con los de bindiff pero el punto fuerte es que es mucho mas preciso que bindiff y el resto de differs a la hora de buscar vulnerabilidades.

Un buen post al respecto lo pueden enconrar aqui.

El source code y el plugin compilado lo pueden encontrar en la web de Corelabs, aqui.

update1: para ser imparciales y no ejercer favoritismos :P debo de decir que hace unos dias estuve probando Bindiff 3.0 y he tenido los mismos resultados que con turbodiff en cuanto a funciones cambiadas, sin embargo, turbodiff sigue siendo un poco mas rapido en el analisis que bindiff pero sin duda este ultimo mejoro bastante desde la version 2.0.

Hasta la proxima!.

miércoles, 14 de octubre de 2009

CollaboREate & IPython for IDAPython

Hola!,

Queria comentarles acerca de dos plugins interesantes para IDA.

Creo que todos conocen IDAPython (el plugin para IDA que permite interactuar con la API de IDA a traves de Python y que ademas nos provee de todas las bondades de python en IDA), bueno resulta que hasta ahora, los que no contamos con las nuevas versiones de IDA (hablo de la > 5.2) a no ser que hayamos comprado una de las caras licencias o tener acceso a alguna distro en nuestro trabajo, debiamos de editar el script de IDAPython en un simple textbox y ademas utilizar el menu o algun atajo de teclado para correr el script, bueno ahora hay una posibilidad mas.

Mediante el script que se encuentra aqui, podemos utilizar el tan conocido interactive shell, IPython, en IDA.

Post original en OpenRCE aqui.

Gracias sagar por el script!.

El segundo plugin sobre el cual queria hablar un poco es CollaboREate.

Se trata de un plugin que permite realizar trabajos de ingenieria inversa con IDA sobre un IDB pero de manera comunitaria. Como es esto? pues dos personas trabajando en un mismo idb, pueden compartir, en tiempo real, todos los cambios que vayan realizando sobre el idb, como renombrar variables, nombres de funciones, parametros, structs, unions, etc etc etc. Solo hace falta montar un server que sea el que envia los datos a todos los que se conecten a el.

Esto quiere decir que el usuario X y el usuario Y que trabajan sobre el mismo idb van a poder trabajar de una manera mas coordinada e instantanea que si tuvieramos que enviar los idbs por mail o subirlos a algun lado en internet, etc. Muy bueno sin duda para trabajos en conjunto.

Homepage de CollaboREate aqui.

Aca un paper sobre el plugin.

Bueno, eso!.

Saludos!.

viernes, 9 de octubre de 2009

El colador de CA (Computer Associates)



Hola!,

Queria contarles acerca de un bug que encontre mientras hacia un exploit para un producto de la compañia CA (Computer Associates - www.ca.com).

El producto en cuestion es el archi-conocido ARCserve Backup, un software corporativo para realizar backups.

Los que trabajan en esta cuestion de buscar bugs y hacer exploits saben de sobra que la mayoria de los productos ofrecidos por esta empresa (CA) pareciera que vienen programados por chicos de 15 años que solo saben utilizar strcpy() y gets(); ARCserve esta lleno de bugs y para comprobarlo, basta con solo colocar "arcserve backup vulnerability" en Google para ver la cantidad de advisories que mencionan vulnerabilidades en este software (acá).

En fin, quiero contarles un poco como fue que di con un bug extra en la misma función que ya tenía otro bug! XD.

La historia fue mas o menos asi:

Estaba tratando de hacer un exploit para CVE-2008-4397. Dicha vulnerabilidad nos permite ejecutar comandos de manera remota, sin autenticacion e incluso lograr dropear un .exe que nos de acceso completo a la maquina victima. Por ejemplo, si enviaramos el comando "cmd /c ntsd -c calc.exe" se ejecutaria el ntsd con la calculadora attacheada.

La funcion vulnerable es accesible mediante RPC (MSRPC). La interfaz que contiene dicha funcion es:


[
uuid(506b1890-14c8-11d1-bbc3-00805fa6962e),
version(1.0)
]


Esa interfaz se encuentra en la libreria Asdbapi.dll y es accesible mediante el servicio llamado "CA Message Service" que escucha en el puerto 6504/TCP y que corre con privilegios de SYSTEM.

La funcion vulnerable es la siguiente:


/* opcode: 0x156, address: 0x28EAAAB0 */

long sub_28EAAAB0 (
[in] handle_t arg_1,
[in][ref][string] char * arg_2,
[in][ref][string] char * arg_3,
[in][ref][string] char * arg_4,
[in][ref][string] char * arg_5,
[in] long arg_6,
[in][ref][size_is(arg_1)] char * arg_7,
[in] long arg_8,
[in, out][ref] long * arg_9,
[out][ref][size_is(*arg_9)] char ** arg_10
);

}


Como podemos ver, el OPCODE que representa a la funcion es el 0x156. Si desensamblamos esta funcion con IDA, veremos que comienza de esta manera:


.text:28EAAAB0 ; int __stdcall sub_28EAAAB0(PRPC_MESSAGE Message)
.text:28EAAAB0 sub_28EAAAB0 proc near
.text:28EAAAB0
.text:28EAAAB0 Args= dword ptr -128h
.text:28EAAAB0 var_124= dword ptr -124h
.text:28EAAAB0 ppMemory= byte ptr -120h
.text:28EAAAB0 var_11C= dword ptr -11Ch
.text:28EAAAB0 var_118= dword ptr -118h
.text:28EAAAB0 var_114= dword ptr -114h
.text:28EAAAB0 pStubMsg= _MIDL_STUB_MESSAGE ptr -110h
.text:28EAAAB0 var_34= dword ptr -34h
.text:28EAAAB0 var_30= dword ptr -30h
.text:28EAAAB0 var_2C= dword ptr -2Ch
.text:28EAAAB0 var_28= dword ptr -28h
.text:28EAAAB0 lpBuffer= dword ptr -24h
.text:28EAAAB0 var_20= dword ptr -20h
.text:28EAAAB0 var_1C= dword ptr -1Ch
.text:28EAAAB0 var_18= dword ptr -18h
.text:28EAAAB0 var_10= dword ptr -10h
.text:28EAAAB0 var_4= dword ptr -4
.text:28EAAAB0 Message= dword ptr 8
.text:28EAAAB0
.text:28EAAAB0 push ebp
.text:28EAAAB1 mov ebp, esp
.text:28EAAAB3 push 0FFFFFFFFh
.text:28EAAAB5 push offset unk_28EC0BC0
.text:28EAAABA push offset _except_handler3
.text:28EAAABF mov eax, large fs:0
.text:28EAAAC5 push eax
.text:28EAAAC6 mov large fs:0, esp
.text:28EAAACD sub esp, 11Ch
.text:28EAAAD3 push ebx
.text:28EAAAD4 push esi
.text:28EAAAD5 push edi
.text:28EAAAD6 mov [ebp+var_18], esp
.text:28EAAAD9 push offset stru_28EBC410 ; pStubDescriptor
.text:28EAAADE lea eax, [ebp+pStubMsg]
.text:28EAAAE4 push eax ; pStubMsg
.text:28EAAAE5 mov esi, [ebp+Message]
.text:28EAAAE8 push esi ; pRpcMsg
.text:28EAAAE9 call ds:NdrServerInitiali


Esa parte corresponde al prologo de la funcion vulnerable. Si nos fijamos, un poco mas abajo realiza un par de comprobaciones sobre los tipos de datos enviados en el paquete, si se corresponde con los tipos esperados, entonces continuara por esta parte:


.text:28EAAC0F loc_28EAAC0F:
.text:28EAAC0F mov [ebp+var_4], ebx
.text:28EAAC12 lea edx, [ebp+ppMemory]
.text:28EAAC18 mov [ebp+var_28], edx
.text:28EAAC1B mov dword ptr [ebp+ppMemory], ebx
.text:28EAAC21 lea eax, [ebp+ppMemory]
.text:28EAAC27 push eax ; ppMemory
.text:28EAAC28 push esi ; int
.text:28EAAC29 push ecx ; int
.text:28EAAC2A mov ecx, [ebp+lpBuffer]
.text:28EAAC2D push ecx ; lpBuffer
.text:28EAAC2E push edi ; nNumberOfBytesToWrite
.text:28EAAC2F mov edx, [ebp+var_124]
.text:28EAAC35 push edx ; int
.text:28EAAC36 mov eax, [ebp+var_34]
.text:28EAAC39 push eax ; int
.text:28EAAC3A mov ecx, [ebp+var_30]
.text:28EAAC3D push ecx ; int
.text:28EAAC3E mov edx, [ebp+Args]
.text:28EAAC44 push edx ; Args
.text:28EAAC45 mov eax, [ebp+var_1C]
.text:28EAAC48 push eax ; int
.text:28EAAC49 call sub_28E19360
.text:28EAAC4E add esp, 28h
.text:28EAAC51 mov [ebp+var_11C], eax
.text:28EAAC57 mov [ebp+pStubMsg.BufferLength], 17h
.text:28EAAC61 cmp esi, ebx
.text:28EAAC63 jz short loc_28E


En la funcion sub_28E19360 es un wrapper que solo pushea los argumentos para la funcion ASDB_ReportRemoteExecuteCML:


.text:28E19360 ; int __cdecl sub_28E19360(int, char Args, int, int, int, DWORD nNumberOfBytesToWrite, LPCVOID lpBuffer, int, int, int ppMemory)
.text:28E19360 sub_28E19360 proc near
.text:28E19360
.text:28E19360 Args= byte ptr 8
.text:28E19360 arg_8= dword ptr 0Ch
.text:28E19360 arg_C= dword ptr 10h
.text:28E19360 arg_10= dword ptr 14h
.text:28E19360 nNumberOfBytesToWrite= dword ptr 18h
.text:28E19360 lpBuffer= dword ptr 1Ch
.text:28E19360 arg_1C= dword ptr 20h
.text:28E19360 arg_20= dword ptr 24h
.text:28E19360 ppMemory= dword ptr 28h
.text:28E19360
.text:28E19360 mov eax, [esp+ppMemory]
.text:28E19364 mov ecx, [esp+arg_20]
.text:28E19368 mov edx, [esp+arg_1C]
.text:28E1936C push eax ; ppMemory
.text:28E1936D mov eax, [esp+4+lpBuffer]
.text:28E19371 push ecx ; int
.text:28E19372 mov ecx, [esp+8+nNumberOfBytesToWrite]
.text:28E19376 push edx ; int
.text:28E19377 mov edx, [esp+0Ch+arg_10]
.text:28E1937B push eax ; lpBuffer
.text:28E1937C mov eax, [esp+10h+arg_C]
.text:28E19380 push ecx ; nNumberOfBytesToWrite
.text:28E19381 mov ecx, [esp+14h+arg_8]
.text:28E19385 push edx ; int
.text:28E19386 mov edx, dword ptr [esp+18h+Args]
.text:28E1938A push eax ; int
.text:28E1938B push ecx ; int
.text:28E1938C push edx ; Args
.text:28E1938D call ASDB_ReportRemoteExecuteCML
.text:28E19392 add esp, 24h
.text:28E19395 retn
.text:28E19395 sub_28E19360 endp


Esta funcion en la responsable de ejecutar los comandos enviados desde el exterior, por ejemplo, si enviamos: "..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\cmd /c \"""\""""

Le estamos indicando el path (mas precisamente, el bug es del tipo path traversal) del cmd que sera el que nos ejecute el comando que le indiquemos con los parametros que le indiquemos.

Los "..\\" son para trigerear la primera de las vulnerabilidades, el path traversal, pero si nos fijamos un poco mas adentro, en una de las funciones (sub_28E3F6B0), tenemos un sprintf():


[...]
.text:28E3F8D9 lea edx, [esp+7C0h+Args]
.text:28E3F8E0 push offset aSSSRSOSS ; "%s\\%s -s -r %s -o %s %s"
.text:28E3F8E5 push edx ; Dest
.text:28E3F8E6 call ds:sprintf
[...]


El bug es obvio, no hay ningun tipo de chequeo sobre el tamaño del string que se va a copiar al stack, con lo cual, enviando como comando un string lo suficientemente "largo" lograriamos sobreescribir el RET de la funcion e incluso el exception handler y saltar a ejecutar codigo.

Previo a llegar a esta zona del bug, hay un chequeo(sub_28E01230) sobre uno de los argumentos que se envian, el paquete debe de contener el hostname de la maquina a la cual estamos atacando:


[...]
.text:28E01250 push eax
.text:28E01251 push offset Buffer
.text:28E01256 call ds:_mbsicmp
.text:28E0125C add esp, 8
.text:28E0125F test eax, eax
.text:28E01261 jz short loc_28
[...]


Si el salto se produce, entonces llegaremos a la zona vulnerable, en caso contrario nos hechara fuera.

Para conseguir el hostname podemos hacer un request utilizando SMB, utilizando python + impacket es sencillo.

Esto que les he comentado, lo probe en la version CA ARCserve Backup r11.5 sin ningun SP ni patch level.

El bug fue arreglado en el SP2 de 11.5 en el cual reescribieron la funcion vulnerable.

Aclaro que en realidad aca son dos bugs. Si se fijan en el PoC mas abajo, lo primero que hacemos es trigerear el path traversal y luego el overflow.


El PoC (Proof Of Concept) lo pueden encontrar aqui:

Bueno, eso es todo por el momento.

Hasta la proxima!.