Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - x4uth

#11
el resultado no es =, el de FeRcHu podria estar toda la vida y no darte un serial valido, xk si la fuerza bruta es fea, si no la haces de manera sistematica es peor... en cambio la otra solucion te daria un serial en nanosegundos.
#12
Tuturial:

empiezo poniendo bp en GetDlgItemTextA meto cualquier dato en el crackme y vemos que para en el kernel, execute until usercode u caemos en
00401F03  |.  E8 78100000   CALL <JMP.&USER32.GetDlgItemTextA>
q es caundo lee el nombre, mas abajo hay otro similar al del pass, asi que aqui estamos, el problema es que si seguimos debugando vemos que estamos en una especie de "message handler", y aqui no es donde procesa los datos, bueno alli vimos que guardo el nombre en 4061A0, asi que ponemos dump 4061A0, y le colocamos un bp Memory on access
alli paro en
0040142B  |.  8038 00       CMP BYTE PTR DS:[EAX],0
alli vemos una funcion que nos recuerda al crackme 1 de karman, comprobamos las entradas y salidas , la salida de EAX esta sospechosa, pero si ejecutamos hasta el ret vemos que esta al final del "message handler" y no hace anda con EAX, asi que no le damos mucha importancia a esta parte
vuelvo a colocar un bpm on acesss pues lo habia quitado para no tener q dar f9 20 veces en la funcion anterior

esta ves cae en 00401759 MOV DWORD PTR SS[ESP+4],crackme.004061A0  , esta metiendo el dato en el stack para llamar un CALL que tiene ad+ de ese otros dos argumentos, uno es
00401755  MOV DWORD PTR SS:[ESP+8],EAX  que es la longitud del nombre y otro q es una zona de memoria con ceros, otra ves quito el bpm para que no moleste debugueo la funcion, no voy a explicar el ensamblador, supongo que todos podeis saber lo q hace debugandola, basicamente va haciendo un xor de todas los caracteres del nombre y un caracter constante que obtiene de [EAX+404078], los resultados de la operacion los guarda en la zona de ceros

al salir del CALL va entrar en otro, esta ves con 2 argumentos , uno es el pass y otro otra zona de ceros
esta tiene dos bucles uno recorre el pass restandole 'A' a cada caracter si es mayor de '?' y restandole 16h en caso contrario, despues entra en otro bucle que hace operaciones logicas con el pass y guarda los resultados en la zona de ceros, pero cada caracter de salida esta formado por 2 de entrada, los caracters pares del pass (0, 2 , 4 ) forman los 4 bits de mayor peso de los BYTEs y los impares la parte baja.

al salir de ese CALL, hace una llamada a(kernel32.SetEvent), y no podemos seguir traceando a mano, bueno seguimos la misma estrategia
buscamos 00401761 en el dump (aqui se guardo el resultado de las operaciones con el nombre) y le ponemos un bpm on acesss, f9 y caemos en
0040167E MOV EAX,DWORD PTR DS:[EDX+EAX]
se trata de una funcion que tratando los priemros 8 bytes los de los resultados anteriores como 2 DWORD, le hace un XOR a estos con otro DWORD que optiene con un AND de otras 2 constantes, asi que lo podemos ver en conjunto como un simple XOR

cuando termina , hace lo mismo con el pass procesado.

despues hace un XOR con las 4 DWORDs, (2 del pass y 2 del name) y comprueba q este sea 0, comprobamos que cuando es 0 nos da el mensaje bueno y cuando es diferente de 0 nos da el mensaje malo, asi que tenemos que lograr que este XOR sea 0.
sabemos que si (a XOR b)==0  entonces a==b

llamando pf al pass procesado final y nf al nombre prosesado final , y p1,n1 al primer procesado del nombre y pass respectivamente
ad+ pf[0] es la primera DWORD obtenida y pf[1] la segunda

j={0,1}

0 = pf[j] XOR  nf[j]
pf[j] = (p1[j] XOR c1[j]) <--  si le mandamos una cadena
de nulos a la funcion que hace el XOR final del pass podemos obtener c1[j] pues (a XOR 0) == a

0 = pf[j] XOR p1[j] XOR c1[j]

p1[j] = pf[j] XOR c1[j]

ahi ya sabemos cuando tiene que dar el primer procesado del pass, asi que solo queda revertir esa funcion

aqui os pongo el codigo en C++ del generador de claves que hize yo


#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>

#define DWORD unsigned int
#define BYTE unsigned char


//0404078h
char const1[8*10];
char const2[16];
char const3[16];


void ShowDump(char* buff, DWORD s)
{
//muestra el contenido de una zona de memoria en hexdecimal
int j,i;
i=0;
for (i=0;i<s;i+=8) {

for (j=i;(j-i)<8;j++){
if (!(j<s)) {
printf ("   ");
continue;

}
if ((unsigned char)buff[j] <= 0xF) printf("0");
printf("%X ",(unsigned char)buff[j]);
if ((j-i)==3) printf("| ");
}

for (j=i;j<s && (j-i)<8;j++){
if (j==i) printf("| ");
if (buff[j]) printf("%c ",buff[j]);
else printf(". ");
}
printf("\n");
}
}

void name1(char * nombre,DWORD len,char * buff)
{
//primer procesamiento del name
  int j,i;
  char c;
 
  for (j=0;j<=7;j++)
  {
  buff[j]=const1[j];
  for (i=0;i<len;i++)
  {
  c=nombre[i];
  c+=c;
  c=c^buff[j];
  buff[j]=c;
  }
  }
}

void pass1(char *pass,char *buff) {
//primer procesamiento del pass
DWORD j;
BYTE b;
char l,h;
for (j=0;pass[j];j++) {
   if (pass[j] > '?') pass[j]-='A'; //se queda con el valor numerico
   else pass[j]-=0x16; //???
}
BYTE i;
for (i=0;i<=7;i++){

l = pass[2*i];
_asm SAR l,1
l &= 0xF; //bit bajo
h = pass[2*i+1];
_asm SAR h,1
_asm SHL h,4
buff[i]=h|l;
}
}

void reversePass1(char *pass,char *buff) {
//revierte el primer proceso del pass
BYTE i,j,b,h,l;
for (j=0;j<8;j++)
{
//bit de menor peso
b=buff[j];
b&=0xF;
b<<=1;
pass[j*2]=b+'A';
//bit de mayor peso
b=buff[j];
b>>=4;
b<<=1;
pass[j*2+1]=b+'A';

}
}

void getDWORD(char * buff,char *cadena,char * garb)
{
DWORD j,i,k;
DWORD *ptrG,*ptrG2,*ptrB;
for (j=0;j<8;j++) buff[j]=cadena[j];
for (j=0;j<=1;j++)
{
for (i=0;i<=1;i++){
if (j==i) continue;

k=2*j+i;
k <<= 2;
ptrG = (DWORD*)((2*i+j)*4+garb);
ptrG2 = (DWORD*)(garb+k);
ptrB = (DWORD*)(buff+(j*4));

k = ptrG[0] & ptrG2[0];
ptrB[0] ^= k;
}
}

}

int main(int argc, char *argv[])
{
char username[16],pass[32],nbuff[16],pbuff[16],n2buff[16],p2buff[16];
memset(const1,0,sizeof(const1));
memset(username,0,sizeof(username));
memset(pass,0,sizeof(pass));
memset(nbuff,0,sizeof(nbuff));   
memset(n2buff,0,sizeof(n2buff));
memset(pbuff,0,sizeof(pbuff));
memset(p2buff,0,sizeof(p2buff));



memcpy(const1,"\x4C\x0D\x18\x6A\x3F\xB9\x25\xE7\xBD\x96\x9A\x91\xDF\x8F\x9E\x8F\x1E\xDE\xDE\xDE\xDF\xA6\x9E\xDF\x8B\x9A\x91\x9A\x8C\xDF\x9E\x93\x98\x90\xDF\x8F\x9E\x8D\x9E\xDF\x8D\x9A\x9C\x90\x8D\x9B\x9E\x8D\xDF\x9C\x8A\x9E\x91\x9B\x90\xDF\x8C\x9A\x9E\x8C\xDF\x89\x96\x9A\x95\x90\xD7\xC0\xC0\xC0\xC0\xD6\x00\x00\x00\x00\x00\x00\x00\x00",sizeof(const1));
memcpy(const2,"\x0D\xEB\xD0\x68\xE4\x6A\x9D\x48\x81\x56\xA3\xE3\x9E\x85\xF1\x7D",sizeof(const2));
memcpy(const3,"\xCA\x78\x8E\x2C\xD5\x61\xA9\x17\xB4\xA5\x96\x87\xF0\xE1\xD2\xC3",sizeof(const3));
system("CLS");
printf("Usuario:");
scanf("%s",username);
strcpy(pass,"");

system("CLS");
ShowDump(username,sizeof(username));
ShowDump(pass,sizeof(pass));
name1(username,strlen(username),nbuff);
ShowDump(nbuff,sizeof(nbuff));
pass1(pass,pbuff);
ShowDump(pbuff,sizeof(pbuff));
getDWORD(n2buff,nbuff,const2);
ShowDump(n2buff,sizeof(n2buff));
getDWORD(p2buff,pbuff,const3);
ShowDump(p2buff,sizeof(p2buff));


//final
DWORD *pdw1,*pdw2;
pdw1=(DWORD*)n2buff;
pdw2=(DWORD*)p2buff;
DWORD res[2];
char * ver= (char*)&res;
memset(pbuff,0,sizeof(pbuff));
memset(pass,0,sizeof(pass));
res[0]=pdw1[0]^pdw2[0];
res[1]=pdw1[1]^pdw2[1];

for (int j=0;j<8;j++) pbuff[j]=ver[j];
reversePass1(pass,pbuff);
ShowDump(ver,8);
ShowDump(pass,sizeof(pass));
for (int j=0;j<80;j++) printf("-");
printf("Usuario:%s\nClave:%s\n",username,pass);

system("PAUSE");
return EXIT_SUCCESS;
}




podeis bajaros el keygen ya compilado aqui ->
http://rapidshare.com/files/68490778/karman02gen.rar.html

una combinacion valida
user: x4uth
pass: ECIEGKOMCMAS]MU]

#13
Cita de: jamonyqueso en  5 Noviembre 2007, 04:32 AM
Hola

Llevo unos dias que no llego a ninguna conclusion y una es esta:

Duda 1:

Hice un programa en Linux y es este

#include <iostream>
int main ()
{
printf " hola nena";
}

Asi de simple  ;D

Y la duda que se me plantea es esta:

Ya compilado con "cc codigo.c"lo abro con Khexedit (de linux) y bien me salen cosas incomprensibles en hex y en ASCII... bien y como explicarlo ummmm...aver ¿Hay alguna manera de entender eso?No digo la parte de Hex si no la ascii,la mayoria son simples puntos y caracteres tipo []  y tengo entendido que el ensamblador y el codigo hexadecimal es equivalente como jne=75 asi que se deberia entender...y creo que no esta cifrado,vamos,no creo que el compilador tenga para encriptarse solo.

y además hay muchos números hexadecimales para tan poca cosa

Y si se puede leer en hex ¿donde encuentro la equivalencias?

como dice ferdu lo recomendado para ver el programa que hcisite es olly y no un editor de hex, aun asi no esperes encontrar
PUSH "hola nena"
CALL printf
que vendria siendo tu programa en asm, esto sera solo una parte, para q el programa se ejecute adecuadamente en tu sistema operativo tiene que realizar una serie de operaciones que las incluye el compilador por su parte, por ejemplo poner lo q haces ahi en asm llebaria unos 20 bytes como maximo, en cambio seguro q tu programa compilado tiene minimo 20 000 bytes eso si no hisiste muchos includes... y si usas funciones como printf directamente de una libreria

Cita de: jamonyqueso en  5 Noviembre 2007, 04:32 AM
Duda 2:

Tengo entendido que la ps1 usa mapas de bits de 256*256 a 16 bits,creo que era asi
Y hay un programa que se llama psmplay que sirve para extraer vídeos,imágenes,mapas de bits y mas... y tenia la idea que desde una imagen recorriera desde el primer bit hasta el ultimo y extrajera los BMP pero la duda es la mayoría de los juegos están metidos en otros archivos mas grandes (como FF8 o el FF9) y suponía que los archivos BMP empiezan desde unas marcas(o unos códigos de iniciación,para saber si es realmente BMP,o JPG tamaño y tal y que acaba en otros)le hago ingieneria inversa a una foto  y mi sorpresa es que impieza por varios "00" en hexadecimal ¬¬ con lo cual mi teoria se fue al traste,aparte de que aparecia la marca de la cámara de photos ¬¬ ...¿como identifico codigo de BMP?
normalmente los empacadores no meten los bytes a pelo, sino que remplazan unos bytes por otros para ahorrar espacio (esto sin hablar de los q encriptan), eso lo hacen mediante algoritmos mas o menos complejos.
Cita de: jamonyqueso en  5 Noviembre 2007, 04:32 AM
Duda 3

¿se puede programar (y que se entienda) en hexadecimal puro?
Yo por lo menos no encuentro ningún tutorial. :-[
por poder se puede, de hecho los primeros programas se hicieron en binario... q lo entiendas y/o y q tengas el tiempo de hacerlo, eso ya es cosa tuya....

Cita de: jamonyqueso en  5 Noviembre 2007, 04:32 AM

Duda 4

Al editar textos ascii en hexadecimal y si te quedas sin espacio para escribir ¿se puede agregar espacios? A mi se me come trozos de código(sobreescribe)....y no hay manera :huh:
por poder puedes , pero como ese texto o algo q este  a continuacion sea usado por otro programa o por el mismo si estas editando un exe ya te lo cargaste


Cita de: jamonyqueso en  5 Noviembre 2007, 04:32 AM
Duda 5

¿por que en los binarios hay tantos 00? y seguidos... :-\
depende del binario q sea, pero es logico q el 0 sea usando de relleno en estructuras de datos


Cita de: jamonyqueso en  5 Noviembre 2007, 04:32 AM
Duda 6

Hay alguna manera de abrir un archivo en plan .RAR y ver sus archivos internos? como los bmp que están dentro de otros archivos grandes como decia antes.
si tiene pass no hay manera de ver nada, si no tiene pass puedes abrirlo y ver su estructura , suelen estar organizados en bloques, cada bloque tiene el nombre del archivo y otros bloques q son partes del archivo comprimidos, pero amos que sin un algoritmo q descomprima no te sirve de nada

Cita de: jamonyqueso en  5 Noviembre 2007, 04:32 AM
Duda 7

¿por que 75 o jne,por ejemplo ,al ejecutarse eso,funciona asi? ¿donde esta programado?Es una duda que siempre quise saber. :rolleyes:
la instruccion JNE y todas las de ensamblador se ejecutan directamente en el CPU, el cpu esta formado por puertas logicas (AND, OR, NOT) que estan formadas basicamente por transistores (silicio dopado). yo no diria que esta programado, mas bien esta diseñado para que su circuito relalize las operaciones nesesarias en cada cadena de niveles bajo y alto (ceros y unos)  que le llegan
#14
segun eso q pusiste ahi el puntero a 092F2EF0 lo tienes en ESI+18
si ESI es constante entonces ya lo tienes resuelto

[0x5087C80+0x18] +0x00000030 +0x4 = direccion del oro
#15
pues no se xk te da ese fallo quiza de tanto duplicarse llegue a un numero imposible
lo otro q puedes hacer es cambiar
895438 04     MOV DWORD PTR DS:[EAX+EDI+4],EDX

por


896438 04     MOV DWORD PTR DS:[EAX+EDI+4],ESP

o sea el 54 por 64,
ESP es el puntero al stack que normalmente es 0012XXXX
con lo cual estas poniendo un numero 1179668++


#16
pues no se me ocurre ninguna manera sencilla de hacerlo :/ pero si lo que quieres es que vaya aumentando y
en [edi+eax+0x4] esta el dinero puedes cambiar el 89 por 01 que seria esto
WriteProcessMemory(hProcess,(LPVOID)0x549539, 1, 1, NULL);
con lo cual tienes
add [edi+eax+0x4],edx
asi aumenta el dinero cada ves que se llame a la funcion (se podria decir q se duplica)
#17
Cita de: msrone en 23 Octubre 2007, 14:48 PM
El problema es que el tsearch me da una direccion, pero esta varia. Como se podria arreglar esto?
eso tiene un cierto nivel de complejidad arreglarlo, el tema es que el programa tenga controlada una variable dinamica tiene q tenerla referenciada por un puntero obligatoriamente, este puntero puedes encontrarlo debugando el codigo que modifica dicha direccion y con un poco de suerte ese puntero tendra una direccion fija, la otra opcion es modificar el codigo del programa , por ejemplo el caso del tiempo del buscaminas q se va incrementando cada segundo, para evitar q se incremente bastaria buscar el lugar donde se incrementa , suponiendo que llegue a esta linea
INC EAX  , tenemos en la direccion de memoria un 0x40 q corresponde a esa operacion, si la cambias por un 0x90 tienes un NOP con lo cual no se incrementaria el tiempo. una tercera forma seria buscar una referencia constante en el bloque de memoria pues muchas veces nuestra variable pertence a una clase o otro tipo de estructura que pueden tener partes constantes, en este caso tendrias q contar los bytes de diferencia, y bastaria con buscar la constante y sumar o restar los bytes de diferencias a la direccion obtenida para obtener la direccion q queremos

Cita de: msrone en 23 Octubre 2007, 14:48 PM
No e podido compilar tu codigo me da error, explicame por favor como puedo compilarlo.
con Visual C++ 2005 compila perfectament, = si me dices el error te puedo ayudar

#18
Cita de: msrone en 23 Octubre 2007, 14:26 PM
Vale perfecto, te e entendido bastante bien.

Mis dudas ahroa es si para determinar un offset por ejemplo del oro, debo de realizar una buskeda en la memoria, con el tsearch por ejemplo viendo donde esta la direccion del oro, y despues como lo paso al offset?
la direccion q te da el tsearch es el offset


Cita de: msrone en 23 Octubre 2007, 14:26 PM
Y la segunda, todo esto puede ponerse dentro de un boton que al pulsar de el resultado de añadir esos 10000 de oro?
claro...


Cita de: msrone en 23 Octubre 2007, 14:26 PM
estoy utilizando el wxdev-C++ pero no puedo compilar tu codigo xq me da error en el NULL...

gracias
no deberia pues el NULL es una constante basica pero bueno pon esto al principio del todo (despues de los includes)
#define NULL 0
#19
claro es lo mismo, para el oro por ejemplo, lo primero es poner el offset correcto
#define OFFSET_TIEMPO 0x100579C  <--- ahi pones el del oro

luego todo igual hasta que lees el oro con
CitarReadProcessMemory(hProcess,(LPVOID)OFFSET_TIEMPO, &tiempo, 4, NULL); 
   

ahi tenemos el oro actual en "tiempo"
asi que le sumamos la cantidad que quieres

tiempo+=10000;
ahi solo te falta escribir ese numero en la memoria


WriteProcessMemory(hProcess,(LPVOID)OFFSET_TIEMPO, &tiempo, 4, NULL);

y el bucle for no haria falta pues en este caso queremos aumentar el oro en una cantidad no dejarlo fijo...


pd. si te fijas ni cambie el nombre de tiempo por oro, pues da lo mismo lo q sea, el nombre de la variable es solo el nombre...
   
#20
no entiendo a que te refieres con recurso, ese ejemplo que te puse modifica la memoria  de otro programa (q en este caso es el tiempo q es de 4 bytes), pero siguiendo ese esquema puedes modicar todo lo que este en la memoria del programa ya sea codigo del programa o variables.

para aprender c++ pos no se :/ en esta misma web hay una subforo de c++ , pasate por ahi y pregunta