|
Mostrar Temas
|
Páginas: [1] 2
|
1
|
Programación / Ingeniería Inversa / Armadillo 4.05
|
en: 27 Enero 2016, 11:53 am
|
Hola muchachos, me he tomado un proyecto un poco personal. He encontrado una aplicación que usa Armadullo 4.05, reportado por Armadillo Inspector. El programa en cuestion, por algun motivo, no corre en mi maquina virtual con Windows XP 32bits en Ollydbg 1.10, asique tengo que usar OllyDBG 2.X He cargado el OllyExt para colocar el parche anti isDebuggerPresent, y Odbgscript para ejecutar los scripts de OllyScript (son del todo compatibles?) Consegui un script de Ricardo para el desempaquetado desde tuts4you, y otro par mas para lo mismo, pero nunca llego al messagebox que deberia decirme que fallo o que tuvo exito.. Cargo el ejecutable, ejecuto el script. Cargo el ejecutable, lo ejecuto y luego ejecuto el script. Siempre habiendo puesto las excepciones que dice Ricardo en el text file, y siempre con el isDebuggerPresent parcheado, pero aun asi, nunca llego al resultado. Que estoy haciendo mal? Que informacion puedo aportar para ayudarme a ayudarlos con mi problema? Saludos! EDIT: Mi problema esta cuando el script ejecuta el programa, cuando salgo del programa se me va al modulo ntdll, y no hay mensaje ni nada. He ido a la ventana del script y dado que ejecute mas alla de la instruccion 'run' pero sigo sin entender como proseguir. Adjunto el script en caso de que alguien quiera verlo.. /* DETACH FARTHER - METHOD RICARDO - VER 0.1 AUTHOR: BENINA Modified hipu' Script by BENINA (HTTP://REAONLINE.NET/FORUM)
Armadillo script - detach parent from client and unpack (1000 bytes method Ricardo)
Debugging Option: Ignore custom exceptions: 0EEDFDE;C0000001..C0009898;80000004
hipu said:
MAKE SURE ALL BREAKPOINTS ARE DELETED BEFORE EXECUTING THE SCRIPT!!!
ALSO: since im using the IsDebuggerPresent plugin, i didnt do IsDebuggerPresent patch. do whatever is needed if u dont use the plugin...
Thanz to Ricardo,Tenketsu and hipu
*/
////////////////////////// // To declare vars /////////////////////////
var WaitForDebugEvent var WriteProcessMemory var pDebugEvent var pBuffer var child_ProcID var oep_offset1 var oep_offset2 var oep_offset3 var crypto_proc var child_OEP var patched_line1 var imgbase var rdata_begin var text_begin var text_patch var tb_report1 var tb_report2 var tb_report3 var tb_report4 var tb_report5 var tb_report6 var addr_1000 var buffer_1000 var temp var temp1
////////////////////////////////////// // Find rdata_begin or (data_begin) /////////////////////////////////////
gmi eip,MODULEBASE mov imgbase, $RESULT mov rdata_begin, imgbase find rdata_begin, #4441544100# //find "DATA" string cmp $RESULT,0 jne lbcontinue
find rdata_begin, #2E726461746100# //find ".rdata" string cmp $RESULT,0 jne lbcontinue
find rdata_begin, #2E6461746100# //find ".data" string cmp $RESULT,0 jne lbcontinue jmp no_run_script lbcontinue: mov rdata_begin, $RESULT add rdata_begin, 0c mov rdata_begin, [rdata_begin] add rdata_begin, imgbase log rdata_begin
///////////////////////////////// // Find text_begin ////////////////////////////////
gmi eip,MODULEBASE mov imgbase, $RESULT mov text_begin, imgbase find text_begin, #434F444500# //find "CODE" string cmp $RESULT,0 jne lbcontinue2
find text_begin, #2E7465787400# //find ".text" string cmp $RESULT,0 jne lbcontinue2 jmp no_run_script
lbcontinue2:
mov text_begin, $RESULT add text_begin, 0c mov text_begin, [text_begin] add text_begin, imgbase log text_begin
///////////////////////////////////////////////////// //eob found_WaitForDebugEvent WriteProcessMemory ////////////////////////////////////////////////////
gpa "WaitForDebugEvent", "kernel32.dll" mov WaitForDebugEvent, $RESULT gpa "WriteProcessMemory", "kernel32.dll" mov WriteProcessMemory, $RESULT
/////////////////////////////////////// //Armadillo check bp first 5 bytes so: ///////////////////////////////////////
add WriteProcessMemory,5 bp WriteProcessMemory run bc WriteProcessMemory sub WriteProcessMemory,5
////////////////////////////////////////////// //Get infomation at bp Call WaitForDebugEvent /////////////////////////////////////////////
bp WaitForDebugEvent run bc WaitForDebugEvent
mov pDebugEvent, esp add pDebugEvent, 04 mov pDebugEvent, [pDebugEvent] log pDebugEvent
mov oep_offset1, pDebugEvent add oep_offset1, 18 mov oep_offset2, pDebugEvent add oep_offset2, 24 mov oep_offset3, pDebugEvent add oep_offset3, 28
//////////////////////////////////////// // Find Child_ProcID and child_OEP ///////////////////////////////////////
bp WriteProcessMemory run bc WriteProcessMemory
mov child_ProcID, pDebugEvent add child_ProcID, 4 mov child_ProcID, [child_ProcID] mov child_OEP, [oep_offset1]
/////////////////////////////////// //Save info Table report ///////////////////////////////////
mov tb_report1,[pDebugEvent]
mov tb_report2,pDebugEvent add tb_report2,4 mov tb_report2,[tb_report2]
mov tb_report3,pDebugEvent add tb_report3,8 mov tb_report3,[tb_report3]
mov tb_report4,pDebugEvent add tb_report4,C mov tb_report4,[tb_report4]
mov tb_report5,pDebugEvent add tb_report5,10 mov tb_report5,[tb_report5]
mov tb_report6,pDebugEvent add tb_report6,14 mov tb_report6,[tb_report6]
//////////////////////////////////////////////////// //Get info in stack at bp Call WriteProcessMemory ///////////////////////////////////////////////////
mov addr_1000,esp add addr_1000,8 mov addr_1000,[addr_1000] log addr_1000
mov buffer_1000,esp add buffer_1000,C mov buffer_1000,[buffer_1000] log buffer_1000
///////////////////////////////// //Patch OEP of Son to EBFE /////////////////////////////////
mov temp,child_OEP sub temp,addr_1000 add temp,buffer_1000 mov temp1,[temp]
and temp1,FFFF eval "Bytes patched at OEP of Son (to invert the bytes order) : {temp1}" msg $RESULT log $RESULT
fill temp,1,eb add temp,1 fill temp,1,fe
/////////////////////////// // FIND ENCRYPTOR ///////////////////////////
mov crypto_proc, esp add crypto_proc, 128 mov crypto_proc, [crypto_proc] add crypto_proc, 2d0 mov [crypto_proc], #9090909090# rtr //ctrl-f9 sto //f8
/////////////////////// //Log info to win log //////////////////////
log "crypto_proc was nopped..." log "patched OEP of child process to EBFE" log child_ProcID log child_OEP
log "press script/resume when ready" eval "Patched successful OEP={child_OEP} of child process (PID= {child_ProcID}) to EBFE !!!!.More Info in Window Log.Press button OK to continues!" msg $RESULT
//////////////////////////////////////////////////////////////// //Patch jump to section .text and NOPs call WaitForDebugEvent ///////////////////////////////////////////////////////////////
bp WaitForDebugEvent run bc WaitForDebugEvent
mov patched_line1, [esp] sub patched_line1, 12
fill patched_line1, 12, 90 add patched_line1,14
eval "jmp {text_begin}" asm patched_line1,$RESULT
add patched_line1,5 eval "NOP" asm patched_line1,$RESULT
////////////////////////////////////// //Patch in section .text (or CODE) //////////////////////////////////////
mov text_patch, text_begin
eval "add dword [{oep_offset1}],1000" asm text_patch,$RESULT
add text_patch,A eval "add dword [{oep_offset2}],1000" asm text_patch,$RESULT
add text_patch,A eval "add dword [{oep_offset3}],1000" asm text_patch,$RESULT
add text_patch,A eval "cmp dword [{oep_offset3}],{rdata_begin}" asm text_patch,$RESULT
add text_patch,A eval "jnz {patched_line1}" asm text_patch,$RESULT
add text_patch,6 eval "push {child_ProcID}" asm text_patch,$RESULT
add text_patch,5 eval "CALL DebugActiveProcessStop" asm text_patch,$RESULT
add text_patch,5 eval "NOP" asm text_patch,$RESULT
////////////////////////////// //Patch in Table report at : //////////////////////////////
sub text_begin,1000 mov [oep_offset1], text_begin mov [oep_offset2], text_begin mov [oep_offset3], text_begin
////////////////////////////////// //go [esp](New origin here) /////////////////////////////////// mov eip, [esp]
////////////////////////// // Set bp F2 at /////////////////////////
bp text_patch run bc text_patch
msg "Successful!.Close OllyDbg, execute again and attach to your newely created process.More Info in Window Log. Have fun." jmp theend
////////////////////////////////// no_run_script: msg "This srcipt don't run with this file. Plz Close Olly.Sorry!"
/////////////////////////////// theend: ret
|
|
|
2
|
Seguridad Informática / Hacking / Una ayudita para este desafio?
|
en: 30 Agosto 2015, 13:15 pm
|
Hola, muchachos. El nombre del desafio es SeSSxploit, lo cual parece que es una referencia a session poisoning. Pero el tema es que no he encontrado como explotarlo.. Posteo el codigo fuente: <?php session_start();
if(!$db = @mysql_connect('localhost', '', '')) { die('Connection error'); } if(!@mysql_select_db('netforce', $db)) { die('Can\'t locate database'); }
if(isset($send) && $send == 'reg' && !isset($_SESSION['Data'])) { if(isset($username) && isset($password)) { $username = htmlspecialchars($username); $password = htmlspecialchars($password); mysql_query("INSERT INTO challenge_406 (id, username, password, ip) VALUES (NULL, '$username', '$password','$_SERVER[REMOTE_ADDR]')") or die('Error!'); $Data['username'] = $username; $Data['password'] = $password; session_register('Data'); echo 'You are added to our database! Click <a href="index.php"><b>here</b></a> to proceed!<br /><br />'; } } else if(isset($submit) && $submit == 'Login' && !isset($_SESSION['Data'])) { if(isset($username) && isset($password)) { $username = addslashes($username); $password = addslashes($password); $checkinfo = mysql_query("SELECT * FROM challenge_406 WHERE username='$username' AND password='$password'") or die('Error!'); $Data = mysql_fetch_array($checkinfo);
if($Data['id'] == '') { die('Wrong password!'); } else { session_register('Data'); header('Location: index.php'); } } } else if(isset($action) && $action == 'register') { ?> <html> <head> <title>Register</title> </head> <body>
<h3>Register now!</h3> <form action="index.php" method="post"> <p> Username:<br /> <input type="text" name="username" size="25" maxlength="12"><br /> Password:<br /> <input type="text" name="password" size="25" maxlength="12"><br /> <input type="hidden" name="send" value="reg"> <input type="submit" value="Register"> </p> </form>
</body> </html>
<?php
} else if(isset($action) && $action == 'logout') { session_destroy(); header('location: index.php'); } else if(isset($_SESSION['Data'])) { $sesname = $_SESSION['Data']['username']; $sespass = $_SESSION['Data']['password']; $checkinfo = mysql_query("SELECT id FROM challenge_406 WHERE username='$sesname' AND password='$sespass'") or die('Error!'); $checkit = mysql_fetch_array($checkinfo); if($checkit['id'] == '') { die('Wrong password!'); } else { if($Data['level'] == '') { $Data['level'] = '0'; }
echo '<p>Welcome to our protected website!</p>'; echo '<ul>'; echo '<li>Username: '.$Data['username'].'</li>'; echo '<li>Admin Level: '.$Data['level'].'</li>'; echo '<li><a href="index.php?action=logout">Logout.</a></li>'; echo '</ul>'; if($Data['level'] == '8') { echo 'Well done! The solution is: [...]'; } } } else {
?> <html> <head> <title>Login</title> </head> <body>
<h3>Login!</h3> <p> Not yet a member? <a href="index.php?action=register">Register a new account.</a><br /> </p> <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> <p> Username:<br /> <input type="text" name="username" size="25" maxlength="12"><br /> Password:<br /> <input type="text" name="password" size="25" maxlength="12"><br /> <input type="submit" name="submit" value="Login"> </p> </form>
</body> </html>
<? } ?>
Por favor, no dar soluciones, solo ayudas.. Si el post no esta permitido, por favor borrarlo.. Saludos!
|
|
|
3
|
Programación / Programación C/C++ / Problema con zLib
|
en: 7 Mayo 2015, 00:25 am
|
Hola, muchachos. Estoy haciendo un editor del formato NBT. Segun la referencia, primero tengo que descomprimirlo (gzip). Asique cargue el archivo entero en un buffer, y cree un buffer laaaaaargo largo como para que me entre la descompresion. Pero cuando llamo a la funcion uncompress me encuentro con error (-3) que me dice que el z_stream esta malformado.. Que puede estar pasando? zcat me lo lee correctamente..
|
|
|
4
|
Programación / Ingeniería Inversa / [RESUELTO] Regresando, me atoré (Ollydbg 2.01 + crackit2 de netforce.nl)
|
en: 15 Noviembre 2014, 17:54 pm
|
Hola, muchachos.. Bueno, que mas decir, cuento lo que he hecho. Cargo el binario, busco las llamadas intermodulares, encuentro que llama a __vbaStrCmp, asique sigo la llamada. Encuentro lo siguiente: 72A29596 /$ FF7424 08 PUSH DWORD PTR SS:[ARG.2] ; /Arg3 = crackit2.4027A4 72A2959A |. FF7424 08 PUSH DWORD PTR SS:[ARG.1] ; |Arg2 => [ARG.1] 72A2959E |. 6A 00 PUSH 0 ; |Arg1 = 0 72A295A0 |. E8 44E6FFFF CALL __vbaStrComp ; \MSVBVM60.__vbaStrComp
Cuando busco en memoria el string que yo entre (prueba) no lo encuentro por ningun lado.. Todas y cada una de esas lineas tienen un breakpoint y en todas y cada una de las lineas lo he buscado.
El desafio se llama "Smartcheck rulez" y es obvio que con Smartcheck seria mas facil (ya de por si te dice que valores se le esta pasando) pero me da por hacerlo solo con Ollydbg, si Smartcheck puede, Olly tambien (supongo, no me peguen muy fuerte que estoy volviendo de a poquito a esto de la ingenieria reversa de codigo ajeno).
La verdad sea dicha, no lei del todo las reglas de la sección, por favor si el thread no esta permitido (nota que no pido la solucion, solo apuntadores) por favor, borrar directamente y avisarme por PM..
O sea, esta pasando los valores como si fuera: __vbaStrCmp(SS:[ARG.2],SS:[ARG.1],0) Que seria lo mismo que decir en Visual Basic StrComp(arg2,arg1,CompareMethod.Text); verdad?
Alguien me podria aclarar la mente, por favor? xD
|
|
|
5
|
Programación / Programación C/C++ / [C/C++] WinAPI -> Problema con SetWinEventHook
|
en: 7 Noviembre 2014, 15:53 pm
|
Hola, muchachos.. Otra vez yo molestando.. Tengo un problema con este hook (lo hago asi por no hacer un polling constante con ::GetForegroundWindow() ) El tema es que por mas que detecta cuando hago el cambio de ventana, no puedo obtener el titulo de la misma.. Posteo a continuacion el codigo de como puse la funcion: HWINEVENTHOOK ventanas = FuncionSetWinEventHook(EVENT_SYSTEM_FOREGROUND,EVENT_SYSTEM_FOREGROUND, NULL,FuncionHookVentanas,0,0,WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
Y aca el codigo de la funcion en la DLL: extern "C" __declspec(dllexport) void RegistrarCambiosDeVentana (HWINEVENTHOOK hWinEventHook, DWORD dwEvento, HWND ventana, LONG idObjeto, LONG idDescendiente, DWORD dwEventThread, DWORD dwMsEventTime) { if (idObjeto != OBJID_WINDOW || idDescendiente != 0) { return; } //if (ventana == NULL) return; ventana = GetForegroundWindow(); int error = GetLastError(); if (error == 0) { char strError[15] = { 0 } ; _itoa_s(error,strError,10); MessageBoxA(NULL,strError,"DLL",MB_OK); } char * strventana = (char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,GetWindowTextLengthA(ventana)*sizeof(char)+1); GetWindowTextA(ventana,strventana,strlen(strventana)+1); MessageBoxA(NULL,strventana,"DLL",MB_OK); HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY,strventana); }
He probado todo, poniendo todas las combinaciones de INCONTEXT y OUTOFCONTEXT, junto con pasarle o no pasarle el handle de la DLL.. Algo mas debo estar haciendo mal porque en si, no entiendo la vuelta de por que no me obtiene el titulo de la ventana que pasa al foreground.. Saludos! PD: El codigo de error que me retorna es 0 (o sea, operacion completada exitosamente, que ironico no? y el parametro que viene desde el sistema tampoco me sirve de nada para sacar el titulo de la ventana, esa es otra cosa que probé..)
|
|
|
7
|
Seguridad Informática / Seguridad / [Youtube] Contador de vistas de video
|
en: 4 Noviembre 2014, 00:36 am
|
Hola muchachos, alguno sabe mas o menos como funciona el tema del contador de visitas de YouTube? O sea, con solo cargar el URL del video no contabiliza, con dejar que descargue el video tampoco, acaso sera que el player reporta algo a algun sitio?
|
|
|
8
|
Programación / Programación C/C++ / [C/C++] WinAPI -> Sockets, me atore.. (resuelto)
|
en: 3 Noviembre 2014, 01:41 am
|
Hola, chicos, me siento mal ultimamente vengo solo a pedir ayuda y no a colaborar.. Tengo un script en PHP que me retorna la IP publica, desde una peticion POST. El tema, es que no se donde estoy pifiandola porque aparentemente no estoy guardando el contenido de lo que me deberia guardar recv() (aclaro que estoy usando un puntero a funcion, por eso en el codigo se va a ver FuncionRecv() Sin mas preambulos, el codigo: char * IPPublica() { WSAData wsaData; SOCKET Socket = INVALID_SOCKET; int codigo_error = 0; struct addrinfo *resultado = NULL, *actual = NULL, pistas; char * ip = (char*)HeapAlloc(GetProcessHeap(),sizeof(char),513); ZeroMemory(&ip,512); char solicitud[512] = "POST /Tracking/Tracker.php HTTP/1.1\r\n" "User-Agent: Mozilla/4.0\r\n" "Host: 127.0.0.1\r\n" "Accept: */*\r\n" "Cache-Control: no-cache\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Lenght: 4\r\n" "ip=1\r\n"; codigo_error = FuncionWSAStartup(MAKEWORD(1,1),&wsaData); if (codigo_error != 0) { FuncionMessageBox(NULL,"Error al inicializar WSA1,1","prueba",MB_OK); FuncionWSACleanup(); return NULL; } ZeroMemory(&pistas,sizeof(pistas)); pistas.ai_family = AF_UNSPEC; pistas.ai_socktype = SOCK_STREAM; pistas.ai_protocol = IPPROTO_TCP;
codigo_error = FuncionGetAddrInfo("127.0.0.1","80",&pistas,&resultado); if (codigo_error != 0 ) { FuncionMessageBox(NULL,"Error al obtener el nombre del host","prueba",MB_OK); FuncionWSACleanup(); return NULL; } for (actual = resultado; actual != NULL; actual = actual->ai_next) { Socket = FuncionSocket(actual->ai_family,actual->ai_socktype,actual->ai_protocol); if (Socket == INVALID_SOCKET) { FuncionMessageBox(NULL,"Fallo el socket","prueba",MB_OK); FuncionWSACleanup(); return NULL; } codigo_error = FuncionConnect(Socket,actual->ai_addr,(int)actual->ai_addrlen); if (codigo_error == SOCKET_ERROR) { FuncionCloseSocket(Socket); Socket = INVALID_SOCKET; continue; } break; } FuncionFreeAddrInfo(resultado); codigo_error = FuncionSend(Socket,solicitud,strlen(solicitud),0); if (codigo_error == SOCKET_ERROR) { FuncionMessageBox(NULL,"Error al enviar","Prueba",MB_OK); FuncionCloseSocket(Socket); FuncionWSACleanup(); return NULL; } codigo_error = FuncionShutdown(Socket,SD_SEND); do { codigo_error = FuncionRecv(Socket,ip,512,0); FuncionMessageBox(NULL,ip,"Prueba",MB_OK); if (codigo_error >0) FuncionMessageBox(NULL,"Recibiedo..","Prueba",MB_OK); else if (codigo_error==0) FuncionMessageBox(NULL,"Conexion cerrada..","Prueba",MB_OK); else { char error[10] = ""; _itoa_s(FuncionWSAGetLastError(),error,10); FuncionMessageBox(NULL,error,"Prueba",MB_OK); } } while(codigo_error > 0); FuncionCloseSocket(Socket); FuncionWSACleanup(); return ip; }
Esta hecho muy a las apuradas.. La verdad que tendria que haberlo hecho todo con Qt que estoy acostumbrado.. Pero se me dio por hacerlo todo con la WinAPI (que sufrimiento, pero ya llevo demasiado escrito como para hechar para atras y de paso aprendo..) Se que me va a devolver el codigo de 200 OK mas los datos, pero tiene todas esas comprobaciones porque en el buffer(ip) no logro obtener ningun contenido
|
|
|
9
|
Programación / Programación C/C++ / [C/C++]No puedo leer MachineGuid (solucionado)
|
en: 2 Noviembre 2014, 22:48 pm
|
Hola muchachos, saben que no me puedo dar cuenta por que me dice que no encuentra la llave, estoy llamandolo asi: char * IDInstalacion() { HKEY llave; BYTE * retornar = NULL; long resultado; resultado = FuncionRegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Cryptography",0,KEY_QUERY_VALUE,&llave); if (resultado != ERROR_SUCCESS) { FuncionMessageBox(NULL,"Error al abrir la llave de registro","Pruebas",MB_OK); } DWORD largo = 0; resultado = FuncionRegQueryValueEx(llave,TEXT("MachineGuid"),NULL,NULL,NULL,&largo); retornar = (BYTE*)HeapAlloc(GetProcessHeap(),sizeof(TCHAR),largo+1); resultado = FuncionRegQueryValueEx(llave,TEXT("MachineGuid"),NULL,NULL,retornar,&largo); char codigo_de_error[512]; _ltoa_s(resultado,codigo_de_error,10); if (resultado != ERROR_SUCCESS){ FuncionMessageBox(NULL,codigo_de_error,"Pruebas",MB_OK); } return (char*)retornar; }
Llamo dos veces a RegQueryValueEx (si, la van a ver como FuncionRegQueryValueEx porque en realidad esta usando un puntero a funcion, la historia es laaaarga pero la resumo: me estoy peleando con otro programa que hace de "control de jefe") una para sacar el largo del valor, y la otra para sacar el valor en si.. Aparte me gustaria que me recomendaran si es mejor usar algun otro Alloc (ajustandose siempre a la WinAPI) PD: feos los casteos pero bueno jeje Saludos! EDIT typo! EDIT2: Dios, siempre me como el OSOO del WOW64, le agregue la clave de SAM KEY_WOW64_64KEY para poderlo trabajar con todo (menos Windows 2000)
|
|
|
10
|
Programación / Programación C/C++ / RegQueryInfoKey -> Retorna un numero erroneo?
|
en: 27 Octubre 2014, 14:52 pm
|
Hola, muchachos, estoy medio atorado con un pedazo de programa que estoy escribiendo.. La idea es listar los programas instalados QUE FIGURAN en "Agregar o Quitar programas".. Pero, el problema viene que RegQueryInfoKey me retorna un valor que nada que ver en cuanto a la cantidad de subclases que una clase tiene en el registro.. A continuacion el codigo: #include <windows.h> #include <stdio.h> #include <tchar.h> #define MAXIMO_NOMBRE_LLAVE 16384 // 16383 + '\0' #define MAXIMO_VALOR_LLAVE 256 // 255 + '\0' void listar_software_instalado() { HKEY llave; TCHAR buffer[512] = ""; DWORD largo_buffer;// = MAX_PATH;
DWORD retcode = RegOpenKey(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",&llave); if (retcode != ERROR_SUCCESS) { printf("Error al abrir la llave\n"); return; } DWORD cantidad_de_subclases = 0; retcode = RegQueryInfoKey( llave, buffer, &largo_buffer, NULL, &cantidad_de_subclases, //NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); if (retcode != ERROR_SUCCESS) { printf("RegQueryInfoKey -> error: %d\n",retcode); return; } DWORD indice = 0; printf("Cantidad de subclases encontradas: %d\n",cantidad_de_subclases); /*for (indice = 0 ; indice < cantidad_de_subclases ; indice++) { printf("Software instalado encontrado (%d)\n",indice); }*/ RegCloseKey(llave); }
En mi caso retorna 446 (?) cuando (contados a mano en esa clase) hay 113.. Pero no entiendo donde le estoy pifiando.. PD: puede haber typos en el codigo porque lo estaba copiando de un papel y ando medio distraido
|
|
|
|
|
|
|