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ú

Temas - Karman

#1
Tras mucho tiempo de no postear en este foro, me decidí hacer este pequeño y tonto crackme para el que tenga ganas de jugar con el... cabe aclarar que es demasiado simple como para parchearlo por lo que la idea es obtener un usuario y clave válido por lo menos (aunque un keygen no es muy complicado una vez entendido el algoritmo)... :P

Sin más preámbulo se los dejo: CrackMe if you can III (Reborn)

S2
#2
Buenas, estoy haciendo un programa con clases y me encontré con una incompatibilidad muy rara de Visual C, el siguiente código funciona perfectamente con GCC pero con Visual C me da error :S

Código (cpp) [Seleccionar]
class XX{
public:
};

class XY{
public:
};

typedef void (XX::*pfun)(void);

class X:public XX,XY{
public:
int ff(int a){
return a;
}
static pfun f;
static struct _t{
pfun f;
}t;
};

pfun X::f=pfun(&X::ff);//??????
struct X::_t X::t={pfun(&X::ff)};//??????


Citar1>main.cpp(28): error C2440: '<function-style-cast>' : no se puede realizar la conversión de 'int (__thiscall X::* )(int)' a 'pfun'
1>          Los punteros a miembros tienen distintas representaciones; no se puede realizar la conversión entre ellos
1>main.cpp(29): error C2440: '<function-style-cast>' : no se puede realizar la conversión de 'int (__thiscall X::* )(int)' a 'pfun'
1>          Los punteros a miembros tienen distintas representaciones; no se puede realizar la conversión entre ellos

si utilizo herencia simple funciona... el tema es con la herencia múltiple:

Código (cpp) [Seleccionar]
class X:public XX,XY

alguno que utilice ese compilador me puede tirar un cable?

S2
#3
Programación C/C++ / Code Virtualization en C
14 Abril 2011, 19:59 PM
buenas, tras tiempo depurando programas con códigos en parte virtualizados se me planteó la duda como hacer un sistema de virtualización de código, por eso armé "esto" que no está completo ni nada, pero que puede llegar a servir de ejemplo supongo  :P

el conjunto de instrucciones no está totalmente definido, solo definí un par de opcodes para hacer pruebas (faltan muchas instrucciones), además no está implementado la parte de modificación de flags del proceso.

#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

/*
REGISTERS
=========
0 eax
2 ebx
E ecx
4 edx
C ebp
6 esp
A edi
8 esi

OPCODES
=======
00 YYYYYYYY ->  jmp long
01 YYYY     ->  jmp short
02 YY       ->  jmp word
03 YYYY     ->  je  short
04 YY       ->  je  word
05 YYYY     ->  jne short
06 YY       ->  jne word

//MOV REG, 00000
14 YYYYYYYY ->  mov eax, long
15 YYYYYYYY ->  mov ecx, long
16 YYYYYYYY ->  mov edx, long
17 YYYYYYYY ->  mov ebx, long
18 YYYYYYYY ->  mov esp, long
19 YYYYYYYY ->  mov ebp, long
1A YYYYYYYY ->  mov esi, long
1B YYYYYYYY ->  mov edi, long

//MOV [REG-X], XXXXXXXX
1C XX YYYYYYYY ->  mov (R) , long ->  X reg X offset

//MOV REG, [REG-X]
1E XX  ->  mov eax, (R) ->  X reg X reg
1F XX  ->  mov ebx, (R)
20 XX  ->  mov ecx, (R)
21 XX  ->  mov edx, (R)
22 XX  ->  mov ebp, (R)
23 XX  ->  mov esp, (R)
24 XX  ->  mov edi, (R)
25 XX  ->  mov esi, (R)

//MOV REG, REG
26 XX  ->  mov R, R

//MOV [REG-X], REG
28 XX  ->  mov (R), eax ->  X reg X offset
29 XX  ->  mov (R), ebx
2A XX  ->  mov (R), ecx
2B XX  ->  mov (R), edx
2C XX  ->  mov (R), ebp
2D XX  ->  mov (R), esp
2E XX  ->  mov (R), edi
2F XX  ->  mov (R), esi

//SUB EDX, EAX
32 XX  ->  sub R, R   ->  X reg X reg

//LEA EAX, [EBP-8]
3C XX  ->  lea eax, (R) ->  X reg X reg
3D XX  ->  lea ebx, (R)
3E XX  ->  lea ecx, (R)
3F XX  ->  lea edx, (R)
40 XX  ->  lea ebp, (R)
41 XX  ->  lea esp, (R)
42 XX  ->  lea edi, (R)
43 XX  ->  lea esi, (R)

*/

typedef struct _REGISTERS{
 ULONG Edi;//00
 ULONG Esi;//04
 ULONG Ebp;//08
 ULONG Esp;//0C
 ULONG Ebx;//10
 ULONG Edx;//14
 ULONG Ecx;//18
 ULONG Eax;//1C
 ULONG Flg;//20
 ULONG Eip;//24
}REGISTERS, *PREGISTERS;

PULONG GetReg(PREGISTERS p,WORD reg){
 PULONG ret=NULL;
 switch(reg){
   case 0x0:// eax
     ret=&p->Eax;
   break;
   case 0x2:// ebx
     ret=&p->Ebx;
   break;
   case 0xE:// ecx
     ret=&p->Ecx;
   break;
   case 0x4:// edx
     ret=&p->Edx;
   break;
   case 0xC:// ebp
     ret=&p->Ebp;
   break;
   case 0x6:// esp
     ret=&p->Esp;
   break;
   case 0xA:// edi
     ret=&p->Edi;
   break;
   case 0x8:// esi
     ret=&p->Esi;
   break;
 }
 return ret;
}

void decrypt(REGISTERS p){
 PBYTE b=(PBYTE)p.Eip;
 BYTE Reg=0,RegEx=0;
 PULONG pReg=0,pRegEx=0;
 CHAR Offset=0;

 //FIX ME!
 b+=2;//lo ideal sería un long jmp, pero gcc no deja setearlo (o no se como)

 //Code Start!
 while(*b!=0xF0){
   switch(*b){
     case 0x1C://MOV [REG-X], XXXXXXXX
       Reg=*(++b);
       Offset=Reg&0xF;
       Reg>>=4;
       if(Reg&0x1)
         Offset=-Offset;
       Reg&=0xE;
       pReg=GetReg(&p,Reg);
       *((PDWORD)(*pReg+Offset))=*(DWORD*)(++b);
       b+=4;
     break;
     case 0x21://MOV EDX, [REG-X]
       Reg=*(++b);
       Offset=Reg&0xF;
       Reg>>=4;
       if(Reg&0x1)
         Offset=-Offset;
       Reg&=0xE;
       pReg=GetReg(&p,Reg);
       p.Edx=*((PDWORD)(*pReg+Offset));
       ++b;
     break;
     case 0x1E://MOV EAX, [REG-X]
       Reg=*(++b);
       Offset=Reg&0xF;
       Reg>>=4;
       if(Reg&0x1)
         Offset=-Offset;
       Reg&=0xE;
       pReg=GetReg(&p,Reg);
       p.Eax=*((PDWORD)(*pReg+Offset));
       ++b;
     break;
     case 0x32://SUB REG,REG
       Reg=*(++b);
       RegEx=Reg&0xF;
       Reg>>=4;
       pReg=GetReg(&p,Reg);
       pRegEx=GetReg(&p,RegEx);
       p.Eax=*pReg-*pRegEx;
       ++b;
     break;
     case 0x28://MOV [REG-X], EAX
       Reg=*(++b);
       Offset=Reg&0xF;
       Reg>>=4;
       if(Reg&0x1)
         Offset=-Offset;
       Reg&=0xE;
       pReg=GetReg(&p,Reg);
       *((PDWORD)(*pReg+Offset))=p.Eax;
       ++b;
     break;
     default:
       //FIX ME!
       b++;//Opcode no válido?
     break;
   }
 }
 p.Eip=(ULONG)++b;
}

void __stdcall vmachine(void);
asm(
 ".globl _vmachine\r\n"
 "_vmachine:\r\n"//function header...
 "  SUB     $0x24,%esp;\r\n"
 "  PUSH    %edi;\r\n"
 "  POP     (%esp);\r\n"
 "  PUSH    %esi;\r\n"
 "  POP     0x4(%esp);\r\n"
 "  PUSH    %ebp;\r\n"
 "  POP     0x8(%esp);\r\n"
 "  PUSH    %ebx;\r\n"
 "  POP     0x10(%esp);\r\n"
 "  PUSH    %edx;\r\n"
 "  POP     0x14(%esp);\r\n"
 "  PUSH    %ecx;\r\n"
 "  POP     0x18(%esp);\r\n"
 "  PUSH    %eax;\r\n"
 "  POP     0x1C(%esp);\r\n"
 "  PUSHF   ;\r\n"
 "  POP     0x20(%esp);\r\n"
 "  LEA     0x28(%esp),%eax;\r\n"
 "  MOV     %eax,0x0C(%esp);\r\n"
 "  CALL    _decrypt;\r\n"
 "  POPA    ;\r\n"
 "  POPF    ;\r\n"
 "  RET"
);

void cryptme(){
 int a,b,c;
 asm(
   " call jmp1;\n\t"
"jmp1:jmp _vmachine;\n\t"
 );
 /*a=15,b=8;c=a-b;*/
 asm(".byte\t\
   0x1C,0xD4,0x0F,0x00,0x00,0x00,\
   0x1C,0xD8,0x08,0x00,0x00,0x00,\
   0x21,0xD4,\
   0x1E,0xD8,\
   0x32,0x40,\
   0x28,0xDC,\
   0xF0\
 ");
 printf("%d %d %d\n",a,b,c);
 return;
}

int main(void){
 cryptme();
 system("pause");
 return 0;
}


el código fue compilado sobre GCC sin ningún tipo de optimización (si se optimiza puede no funcionar correctamente porque el compilador elimina las variables sin referencias directas u otros tipos de optimizaciones)

el código:

 asm(
   " call jmp1;\n\t"
"jmp1:jmp _vmachine;\n\t"
 );


se lo podría meter en una macro pero como era solo para probar lo posteo así (de paso queda a la vista para el que le interese portarlo a otro compilador).

el resultado es el siguiente, el código sin virtualizar en un debugger como olly sale:

void cryptme(){
 int a,b,c;
 a=15,b=8;c=a-b;
 printf("%d %d %d\n",a,b,c);
 return;
}


Código (asm) [Seleccionar]
004015F2  /$  55            PUSH    EBP
004015F3  |.  89E5          MOV     EBP, ESP
004015F5  |.  83EC 28       SUB     ESP, 28
004015F8  |.  C745 FC 0F000>MOV     DWORD PTR SS:[EBP-4], 0F         ; |
004015FF  |.  C745 F8 08000>MOV     DWORD PTR SS:[EBP-8], 8          ; |
00401606  |.  8B55 F8       MOV     EDX, DWORD PTR SS:[EBP-8]        ; |
00401609  |.  8B45 FC       MOV     EAX, DWORD PTR SS:[EBP-4]        ; |
0040160C  |.  29D0          SUB     EAX, EDX                         ; |
0040160E  |.  8945 F4       MOV     DWORD PTR SS:[EBP-C], EAX        ; |
00401611  |.  8B45 F4       MOV     EAX, DWORD PTR SS:[EBP-C]        ; |
00401614  |.  894424 0C     MOV     DWORD PTR SS:[ESP+C], EAX        ; |
00401618  |.  8B45 F8       MOV     EAX, DWORD PTR SS:[EBP-8]        ; |
0040161B  |.  894424 08     MOV     DWORD PTR SS:[ESP+8], EAX        ; |
0040161F  |.  8B45 FC       MOV     EAX, DWORD PTR SS:[EBP-4]        ; |
00401622  |.  894424 04     MOV     DWORD PTR SS:[ESP+4], EAX        ; |
00401626  |.  C70424 983040>MOV     DWORD PTR SS:[ESP], CodeVirt.004>; |ASCII "%d %d %d\n"
0040162D  |.  E8 56080000   CALL    <JMP.&msvcrt.printf>             ; \printf
00401632  |.  C9            LEAVE
00401633  \.  C3            RETN


sin embargo, el código virtualizado se ve:

Código (asm) [Seleccionar]
004015F2  |$  55            PUSH    EBP
004015F3  |.  89E5          MOV     EBP, ESP
004015F5  |.  83EC 28       SUB     ESP, 28
004015F8  |.  E8 00000000   CALL    CodeVirt.004015FD
004015FD  \$^ EB B9         JMP     SHORT CodeVirt.004015B8
004015FF      1C            DB      1C
00401600      D4            DB      D4
00401601      0F            DB      0F
00401602      00            DB      00
00401603      00            DB      00
00401604      00            DB      00
00401605      1C            DB      1C
00401606      D8            DB      D8
00401607      08            DB      08
00401608      00            DB      00
00401609      00            DB      00
0040160A      00            DB      00
0040160B      21            DB      21                               ;  CHAR '!'
0040160C      D4            DB      D4
0040160D      1E            DB      1E
0040160E      D8            DB      D8
0040160F      32            DB      32                               ;  CHAR '2'
00401610      40            DB      40                               ;  CHAR '@'
00401611      28            DB      28                               ;  CHAR '('
00401612   .  DCF0          FDIVR   ST, ST                           ; |
00401614   .  8B45 F4       MOV     EAX, DWORD PTR SS:[EBP-C]        ; |
00401617   .  894424 0C     MOV     DWORD PTR SS:[ESP+C], EAX        ; |
0040161B   .  8B45 F8       MOV     EAX, DWORD PTR SS:[EBP-8]        ; |
0040161E   .  894424 08     MOV     DWORD PTR SS:[ESP+8], EAX        ; |
00401622   .  8B45 FC       MOV     EAX, DWORD PTR SS:[EBP-4]        ; |
00401625   .  894424 04     MOV     DWORD PTR SS:[ESP+4], EAX        ; |
00401629   .  C70424 983040>MOV     DWORD PTR SS:[ESP], CodeVirt.004>; |ASCII "%d %d %d\n"
00401630   .  E8 53080000   CALL    <JMP.&msvcrt.printf>             ; \printf
00401635   .  C9            LEAVE
00401636   .  C3            RETN


con lo cual se ve claramente la diferencia...

lo que se podría agregar al código es (como ya dije) un conjunto más variado de instrucciones y luego un "virtualizador" que convierta las instrucciones normales a las virtualizadas, pero, ese ya es un arduo trabajo y si a alguien le interesa tomarlo como proyecto podría ayudar  :P

S2
#4
Programación C/C++ / Pattern Scanner
6 Marzo 2011, 09:56 AM
Un Pattern Scanner es una función capaz de "encontrar" algo que nos interesa en un módulo externo (puede utilizarse incluso sobre otro proceso aunque ya es más complicado) sin importar la versión de ese módulo (dll,exe,etc.), la única condición para que nuestro Pattern Scanner funcione es que lo que tomamos de referencia no varíe en las distintas versiones de dicho módulo.

Lo primero que se debe hacer es definir que se quiere obtener (esto puede ser una variable o función de dicho módulo del cual no se tengan referencias para llegar), para hacerlo se puede hacer uso de ingeniería inversa (o sea, desensamblar el módulo).

Veamos un ejemplo (en nuestro propio módulo con el fin de visualizarlo): creamos un simple programa con una sola función:

#include <windows.h>

char titulo[]="titulo";
char mensaje[]="un mensaje";

void funcionascanear(void){
 MessageBox(0,mensaje,titulo,0);
}

int main(void){
 funcionascanear();
 return 0;
}


abrimos nuestro programa con ollydbg y buscamos nuestra función:

Código (asm) [Seleccionar]
004012D0  /$  55                 PUSH    EBP
004012D1  |.  89E5               MOV     EBP, ESP
004012D3  |.  83EC 18            SUB     ESP, 18
004012D6  |.  C74424 0C 00000000 MOV     DWORD PTR SS:[ESP+C], 0          ; |
004012DE  |.  C74424 08 00204000 MOV     DWORD PTR SS:[ESP+8], generico.0>; |ASCII "titulo"
004012E6  |.  C74424 04 07204000 MOV     DWORD PTR SS:[ESP+4], generico.0>; |ASCII "un mensaje"
004012EE  |.  C70424 00000000    MOV     DWORD PTR SS:[ESP], 0            ; |
004012F5  |.  E8 86080000        CALL    <JMP.&USER32.MessageBoxA>        ; \MessageBoxA
004012FA  |.  83EC 10            SUB     ESP, 10
004012FD  |.  C9                 LEAVE
004012FE  \.  C3                 RETN


en base a este código ASM crearemos un "patron" que nos lleve a dicha función (nuestro objetivo en este caso será modificar el mensaje)

Citar55                            PUSH    EBP
89E5                         MOV     EBP, ESP
83EC 18                    SUB     ESP, 18
C74424 0C 00000000 MOV     DWORD PTR SS:[ESP+C], 0          ; |
C74424 08 00204000 MOV     DWORD PTR SS:[ESP+8], generico.0>; |ASCII "titulo"
C74424 04 07204000 MOV     DWORD PTR SS:[ESP+4], generico.0>; |ASCII "un mensaje"
C70424 00000000      MOV     DWORD PTR SS:[ESP], 0            ; |
E8 86080000             CALL    <JMP.&USER32.MessageBoxA>        ; \MessageBoxA
83EC 10                    SUB     ESP, 10
C9                            LEAVE
C3                            RETN

lo que está en rojo será nuestro patrón (se lo puede complicar más, y es preferible, pero para nuestro ejemplo servirá), por lo tanto generamos una función que lo detecte:

char *findmsgbypattern(){
 unsigned char *p;
 //dirección inicio / fin del escaneo
 for(p=0x00401000;p<0x00401FFF;p++){
   //nuestro patron
   if(p[0]==0x55&&p[1]==0x89&&p[3]==0x83&&p[6]==0xC7&&p[14]==0xC7&&p[22]==0xC7){
     //dirección de la variable tomada del código
     return (char *)*(void**)&p[26];
   }
 }
 return NULL;
}


Un detalle a destacar de la función es que &p[26] nos devolverá la dirección de memoria de la instrucción, pero no de la variable, entonces mediante el *(void**) obtendremos la verdadera dirección.

Ahora ya podemos escanear nuestro código, y en caso de encontrar nuestra variable modificarla:

#include <windows.h>

char titulo[]="titulo";
char mensaje[]="un mensaje";

void funcionascanear(void){
 MessageBox(0,mensaje,titulo,0);
}

char *findmsgbypattern(){
 unsigned char *p;
 //dirección inicio / fin del escaneo
 for(p=0x00401000;p<0x00401FFF;p++){
   //nuestro patron
   if(p[0]==0x55&&p[1]==0x89&&p[3]==0x83&&p[6]==0xC7&&p[14]==0xC7&&p[22]==0xC7){
     //dirección de la variable tomada del código
     return (char *)*(void**)&p[26];
   }
 }
 return NULL;
}

int main(void){
 char *msg=findmsgbypattern();
 if(msg)
   strcpy(msg,"mi mensaje");
 funcionascanear();
 return 0;
}


Solo cabe aclarar que en el caso de modificar un string la variable original debe ser de un tamaño adecuado para nuestra modificación.

S2

PD: El ejemplo fue compilado con Mingw (GCC), es casi seguro que no funcione en otros compiladores (VC, etc), para hacerlo funcionar hay que rearmar el patrón.

PD2: Existen librerías que permiten buscar patrones de forma más sencilla, como por ejemplo (formato olly):

findpattern(dirinicio,dirfin,"XX????XX??????XX????XX");

pero lo que hacen al fin y al cabo es lo mismo.
#5
PHP / Simple AntiBot en PHP
19 Febrero 2011, 05:16 AM
bueno, dado que estaba sufriendo varios ataques en mi web (no se ni me interesa de quien) tube que implementar un antibot parecido al que se usaba en este sitio (inspirado en lo que puso el-brujo en un post aunque mucho más simple)

Código (php) [Seleccionar]
<?php /* antibot.php */

function checkBot(){
//cookie params
@ini_set('session.use_cookies',1);
@ini_set('session.cookie_lifetime',31536000);//un año
@ini_set('session.use_only_cookies',1);
@ini_set('session.cookie_path','/');
// configufación de variables PHP
@ini_set('session.name',"AntiBot");//nombre de la cookie
//otras opciones   
@ini_set('session.hash_function',0);
@ini_set('session.use_trans_sid',0);
@ini_set('session.save_path','/tmp');
@session_start();

if(!isset($_SESSION['bottime']))
$_SESSION['bottime']=rand(100,999);
$bottime=$_SESSION['bottime'];

if(isset($_REQUEST['antibotkey']))
$_SESSION['antibotkey']=$_REQUEST['antibotkey'];
if(isset($_SESSION['antibotkey'])&&isset($_SESSION['bottime'])){
$antibotkey=$_SESSION['antibotkey'];
if(!empty($antibotkey)&&sha1($_SERVER['HTTP_USER_AGENT'].$bottime)==$antibotkey)
  return null;
}

if(!isset($_SESSION['botcount']))
$_SESSION['botcount']=0;
else
$_SESSION['botcount']++;

if($_SESSION['botcount']>10){
$_SESSION['botcount']=0;
@session_write_close();
@header("Location: http://www.google.com");
}

return sha1($_SERVER['HTTP_USER_AGENT'].$bottime);
}

?>


Código (php) [Seleccionar]
<?php /* index.php */
/********************************* Anti Bot ************************************/

include 'antibot.php';
$antibotkey=checkBot();
if(!empty(
$antibotkey))
die("<a href='index.php?antibotkey=$antibotkey'>Haz Click Aquí para Entrar al Sitio</a><br/><br/>Este Mensaje es mostrado para evitar el ingreso de Bots y solo lo verás una vez.<br/><br/>Disculpe las molestias.");

/********************************* Anti Bot ************************************/


se puede optimizar, se le pueden agregar más checkeos, etc... pero es para tener una base dado que la que se utilizó acá en el foro no es público el código... je  :xD, pero como supongo es algo temporal no me calenté mucho en mejorarlo :)

S2

PD: El protocolo no es ese, pero es perecido, je
#6
bueno... gracias a que este foro me ayudó en la parte del wall (http://foro.elhacker.net/programacion_cc/empezar_a_codear_tu_propio_cheat_half_life-t176966.0.html;msg1309570#msg1309570), dejo acá un wallhack para el SXE 8.0 todos los fix... aclaro... este wall solamente fue probado en mi máquina así que desconozco si funcione siquiera en las suyas... :silbar:
prueben y después avisan... :P

2º Este es mi primer y único wall... así que no me vayan a estar mandando msg pidiéndome otro... si les funciona y les gusta... ok... sinó... lo siento... :P

acá el video (Anti Local Ban):


acá el video (Cheat FX 6):


Fix FX 6 (Test Mode)[Fuera el wall]


Activación por teclado/menu:

Citar======================================================
F3: Panic Key
F4: Menu
======================================================


Este Fix no supone modificación alguna a la versión FX 5 más que la activación por menu y el anti local ban... así que quedan vigentes las características anteriores...

Mayor cantidad de placas de video... (hasta acá llego... si no les funciona su placa de video es incompatible!)
Compatibilidad con Counter-Strike 1.5
Compatibilidad con Windows Vista (en la PC de un amigo anda... :silbar:)


S2

Nota: El cheat solo funciona en OPENGL MODE, dejen de mandarme privados diciendo que no anda y tienen el juego en DIRECTX


PD: A partir de ahora no daré mas soporte, lucio32( Gabriel@Privated.com.ar ) se encargará del mismo y cualquier problema groso me lo comunicará...
#7
buenas, estoy desarrollando un proyecto bajo PHP (antiormente hable de el) y el tema es que me topé con una duda de como hacer lo siguiente:

Tengo un conjunto de módulos los cuales pueden necesitar sus propias tablas en la base de datos, el tema es que cada uno de estos módulos puede tener múltiples instancias (algo así como: blog de pepito, blog de josesito), pero en si, el código que maneja el módulo "blog" es uno solo, entonces mi duda es como crear esas tablas en la base de datos:

1º Una única tabla con un identificador de instancia (1 petito, 2 josesito), el tema de esta opción es que siquiero borrar un determinado blog, tendría que hacer todo un laburo extra para eliminar unicamente las entras del X blog, y si ya no hay instancias, borrar toda la tabla...

2º Una tabla por instancia cuyo nombre esté relacionada con el nombre de esta (blog_pepito,blog_josesito), con esta opcion desaparecen las complicaciones anteriores pero aparece la complicación de mantener ese nombre de tabla en algún lado (en mi caso tengo a dispoción "variables del módulo"), pero si dicha "variable" por alguna razón desaparece (o se borra) perdería la relación con la base de datos...

3º Una tabla por instancia cuyo nombre esté relacionado con el módulo/instancia (blog_1,blog_2), con esta otra opción desaparecen las complicaciones de las anteriores pero se dificulta la lectura de la base de datos... (en realidad me parece un poco complicada...)

bueno... espero se entienda la idea y me dén alguna opinión...

S2
#8
Bueno, los que me hayan leído mis últimos post verán que arme una clase para desarmar la clásica estructura PE... el tema es que hacía un tiempo había visto el código de un crypter simple en este foro (para ser más exacto http://foro.elhacker.net/programacion_cc/source_crypter_simple-t204227.0.html;msg969905#msg969905) el cual no funcionaba muy bien (con algunos ejecutables el resultado era desastroso) porque no tenía en cuenta un par de cosas que he agregado a este nuevo crypter...

Antes que nada paso a explicar un par de cosas para que a los que le interese el código puedan seguirlo...

1º y fundamental... los tipos de direccionamiento (la parte más complicada...  :P), bueno... en esta clase que cree hay 3 tipos básicos de direccionamiento:
A:Por Offset: la clase lo que hace es subir a memoria el archivo, entonces este tipo de direccionamiento nos lleva directamente a una posición de memoria del archivo, osea suponiendo que nuestra variable que contiene el contenido del archivo se llame buffer:

CitarOffset(10) => &buffer[10]
*Offset(0) = 'M';*Offset(1) ='Z';

B: Por RVA: la clase es capaz de resolver direcciones virtuales, en este caso al setear un valor, se calculará el offset de acuerdo a este valor y obtendremos la posición de memoria del archivo... por ejemplo:

si una sección empieza físicamente en 400, pero tiene una dirección virtual de 1000, al hacer:

CitarRVA(1024) = &buffer[424]

sin importar en cual sección se encuentre... (el algoritmo se encarga de eso)
C: por dirección referenciada: esta última opción (que agregué en esta versión) permite obtener el offset real de una dirección (la inversa de Offset), por ejemplo si tenemos una dirección 0x431212 y queremos saber en que punto del archivo se encuentra:

Address(0x431212) = 325
Offset(325) = 0x431212


bueno, ahora si el código:

Código (cpp) [Seleccionar]
/////////////////////////////////////////////////////////////////////////////
// Name:        PE simple crypter (FIX 1)
// Purpose:     Encriptador simple de Ficheros PE
// Author:      Karman
// Created:     2009-10-7
// Copyright:   (c) Exinferis Inc
// Web:         http://www.inexinferis.com.ar
// Vr. : 0.1.1
/////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include "ExecAnalizer.h"

CCHAR DataDirectories[][24]={
 "Export Table",
 "Import Table",
 "Resource Table",
 "Exception Table",
 "Certificate Table",
 "Relocation Table",
 "Debug Table",
 "Architecture Table",
 "Machine Table",
 "Thread Local Storage",
 "Load Config Table",
 "Bound Import Table",
 "Import Address Table",
 "Delay Import Table",
 "COM+ Runtime Header"
};

BYTE ourcode[]={
 //push old entrypoint...
 0x68,0x00,0x00,0x00,0x00,
 //push size of code
 0x68,0x00,0x00,0x00,0x00,
 //push address of code
 0x68,0x00,0x00,0x00,0x00,
 //call decrypt
 0xE8,0x00,0x00,0x00,0x00,
 //Ret
 0xc3
};

DWORD WINAPI GetFunctionSize(PBYTE dwStart);
VOID  WINAPI descifrar(PBYTE address,INT size, DWORD oep);
VOID  WINAPI cifrar(PBYTE address,INT size);

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPInst,LPSTR lpCmd,int nShow){
 DWORD nImageBase,nEntryPoint;
 PIMAGE_NT_HEADERS pINH;
 PIMAGE_SECTION_HEADER pISHCode;
 PCHAR forig="C:\\WINDOWS\\regedit.exe";
 PCHAR fcrytp="C:\\WINDOWS\\cifrado.exe";
 printf("Abriendo -> %s\n",forig);
 ExecAnalizer crypt(forig);
 //nos aseguramos que sea PE...
 if(crypt.GetDOSHeader()&&crypt.HasNewHeader()&&crypt.IsPE()){
   printf("\tFile Is -> PE\n");
   pINH = crypt.GetNTHeader();
   //datos básicos del ejecutable
   nEntryPoint=pINH->OptionalHeader.AddressOfEntryPoint;
   nImageBase=pINH->OptionalHeader.ImageBase;
   printf("\tEntryPoint -> %X\n",nEntryPoint);
   printf("\tImageBase -> %X\n",nImageBase);
   puts("Buscando Code Section:");
   //sección del código
   pISHCode=crypt.RVA2Section(nEntryPoint);
   if(pISHCode){
     printf("\tCode Section Found At -> %X\n",crypt.Address2Offset((PBYTE)pISHCode));
     DWORD codeStart=pISHCode->VirtualAddress;
     DWORD codeEnd=pISHCode->VirtualAddress+pISHCode->SizeOfRawData;
     printf("\tCode Section Start At -> %X\n",codeStart);
     printf("\tCode Section End At -> %X\n",codeEnd);
     //buscamos si alguna otra cosa se encuentra tb en el area de código
     puts("Buscando Tablas en Code Section (Calculando tamaño real del código)");
     for(int i=0;i<15;i++){
       if(pISHCode==crypt.RVA2Section(pINH->OptionalHeader.DataDirectory[i].VirtualAddress)){
         printf("\t%s is in Code Section At %X - %X\n",DataDirectories[i],
           pINH->OptionalHeader.DataDirectory[i].VirtualAddress,
           pINH->OptionalHeader.DataDirectory[i].Size
         );
         DWORD tAdress=pINH->OptionalHeader.DataDirectory[i].VirtualAddress;
         DWORD tSize=(pINH->OptionalHeader.DataDirectory[i].VirtualAddress+pINH->OptionalHeader.DataDirectory[i].Size);
         if(nEntryPoint<tAdress){
           if(codeEnd>tAdress)
             codeEnd=tAdress;
         }else{
           if(codeStart<tSize)
             codeStart=tSize;
         }
       }
     }
     puts("Tamaño real del código:");
     printf("\tCode Section Start At -> %X\n",codeStart);
     printf("\tCode Section End At -> %X\n",codeEnd);
     // Valores reales (en el archivo)
     DWORD rCodeStart=(DWORD)crypt.RVA2Offset(codeStart);
     DWORD rCodeEnd=(DWORD)crypt.RVA2Offset(codeEnd);
     //buscamos espacio libre dentro de la sección code para copiarnos...
     puts("Buscando Espacio para nuestro Código:");
     //tamaño de nuestro código...
     DWORD decrypcodefuncsize=GetFunctionSize((PBYTE)descifrar);
     DWORD decrypcodesize=decrypcodefuncsize+0x20;
     //Espacios libres???
     DWORD dwBlanks=0,dwAddress=(pISHCode->PointerToRawData+pISHCode->SizeOfRawData);
     for(;((dwAddress>rCodeEnd)&&(dwBlanks<decrypcodesize));dwAddress--)
       if(!*crypt.OffsetValue(dwAddress))dwBlanks++;else dwBlanks=0;
     //tiene espacio???
     printf("\tEspacio Necesario: %X - Espacio encontrado: %X\n",decrypcodesize,dwBlanks);
     if(decrypcodesize>=dwBlanks){
       printf("\tFree Space At -> %X\n",dwAddress);
       //ciframos...
       cifrar((PBYTE)crypt.RVAValue(codeStart),codeEnd-codeStart);
       //copiamos la función que descifra
       memcpy((PVOID)crypt.OffsetValue(dwAddress),(PVOID)descifrar,decrypcodefuncsize);
       //armamos cabecera...
       *(DWORD *)&ourcode[0x01]=nEntryPoint+nImageBase;
       *(DWORD *)&ourcode[0x06]=codeEnd-codeStart;
       *(DWORD *)&ourcode[0x0B]=codeStart+nImageBase;
       *(DWORD *)&ourcode[0x10]=-(decrypcodefuncsize+20);
       dwAddress+=decrypcodefuncsize;
       memcpy((PVOID)crypt.OffsetValue(dwAddress),(PVOID)ourcode,24);
       //calculamos nuevo entrypoint
       pINH->OptionalHeader.AddressOfEntryPoint=crypt.Offset2RVA(dwAddress);
       // Damos permiso de escritura a la sección. Si no hacemos esto nos dara error.
       pISHCode->Characteristics |= IMAGE_SCN_MEM_WRITE;
       // Corregimos tamaño de la sección virtual si insuficiente
       if(pISHCode->Misc.VirtualSize<(crypt.Offset2RVA(dwAddress)-pISHCode->VirtualAddress+24))
         pISHCode->Misc.VirtualSize=(crypt.Offset2RVA(dwAddress)-pISHCode->VirtualAddress+24);
       crypt.Save(fcrytp);
     }else
       puts("\tSin espacio Suficiente... :(");
   }
   
   system("pause");
 }
}

DWORD WINAPI GetFunctionSize(PBYTE dwStart){
 PBYTE dwEnd=dwStart;
while(*dwEnd!=0xC3&&*dwEnd!=0xC2)dwEnd++;
if(*dwEnd==0xC2)return (dwEnd-dwStart+3);
return (dwEnd-dwStart+1);
}

VOID  WINAPI descifrar(PBYTE address,INT size, DWORD oep){
 while(size>0){
   *(address++)^=0x65;
   size--;
 }
 //set ret to old entry point
 asm("mov %0 , 0x04(%%esp)"::"r"(oep));
}

VOID  WINAPI cifrar(PBYTE address,INT size){
 while(size>0){
   *(address++)^=0x65;
   size--;
 }
}


Detalles a destacar a diferencia de la primera versión del cripter:
1º Checkeo "de qué se cifra": el código no cifra toda la sección CODE, ya que muchos compiladores tienen la opción de combinar dentro de la sección CODE otras estructuras (IMPORT por ejemplo), y al cifrar esta estructura el programa ya no es válido (el cifrado de la IAT va más allá de este simple código, además de que desconozco como realmente se hace)...

2º Corrección de secciones: nuevamente el código anterior agregaba su código dentro de la sección CODE, pero no verificaba que esta modificación esté dentro de los valores definidos en la sección...

3º El código para descifrar mantiene cierta "lógica" secuencial, (aunque no logré hacer funcionar el código original) cuando lo intentaba debuggear los debuggers no lo entendían...

bue... eso es todo...  :P ...

S2

PD: me olvidaba de poner la dir del code:

Crypter Simple

PD2: Desconozco si el código tenga algún problema... con los ejecutables que probé funcionó...  :P
#9
Buenas, estoy desarrollando un miniframework con el cual estoy armando páginas para varios clientes con distintas bases de datos y configuraciones de servidor... (dos puntos que me han quebrantado hasta hoy), la idea de este post es exponer como lo estoy desarrolando para ver si se puede mejorar y obviamente facilitar mi vida..  :P

La idea actual es la siguiente, está totalmente programado en objetos y tiene un solo archivo direccionador (index.php)

Hay una clase base X(base), que es la index.php crea, esta clase se encarga de inicializar la base de datos (objeto), obtener información de la versión del software y otras configuraciones generales (en DB), inicializar sesiones(objeto), obtener datos de usuarios(objeto), (si sesiones le dice que hay alguno) y obtener parámetros enviados...

Si todo ok... index.php llama a "X->visualizar", función que se encarga de crear un objeto Módulo que se crea en base a los parámetros enviados... cada módulo está en DB y tiene su grupo de variables de módulo y dos especiales que son Archivos y Secciones...

El método principal del Objeto módulo tiene únicamente dos respuestas... Falso si no existe el módulo o el usuario no tiene permisos, o el resultado del modulo en si (aclaro que trabajo con Smarty ), el módulo (dependiendo de las variables del mismo) crea dos subclases (secciones y archivos), dichas clases son dependientes del módulo, otorgando o restringiendo permisos dependiendo del módulo y usuario (un módulo no puede borrar un archivo de otro módulo o un usuario con pocos permisos no puede eliminar una sección de un usuario con más permisos, etc...), osea quedaría esta estructura (mas o menos)

Citar
       index.php
              |
         sistema
       /      |      \
   DB  sesiones  usuarios
       \      |       /
          modulo
         /     |     \
  archivos |  secciones (o categorías)
         \     |     /
       modulo en si (noticias, descargas, etc...)

ustedes que piensan? como se podría mejorar?

S2
#10
buenas, tengo una duda que me está volviendo loco, tengo una tabla del siguiente tipo:


eid | sid | data
1     1    "lara lara"
1     1    "qewrqer"
2     1    "asdfasdf"
2     1    "lara lara"
3     1    "qewrqer"
3     0    "zxcvzcv"


falta el identificador del tabla pero es solo un campo auto incremental...

el tema es que: necesito obtener todos los datos que no pertenezcan a un "eid", que pertenezcan a un "sid" y que no se repitan... por ejemplo:


eid | sid | data
1     1    "lara lara"
2     1    "asdfasdf"


cuando el eid sería 3 y el sid sería 1... actualmente lo estoy haciendo de una forma un tanto embrollada:

obtengo todos los "data"'s distintos que pertenezcan al sid 1, todos los "dats"'s distintos del eid 3 sid 1, y hago una diferencia de arreglo, eso me devuelve:

"lara lara","asdfasdf"

por lo que luego tengo que buscar la primera referencia en la tabla a un "lara lara" o un "asdfasdf" y obtengo el resultado... pero es muy embrollado y no me parece eficiente...

Alguna idea de como puedo hacerlo de otra forma?

S2
#11
PHP / Arbol ordenado en SQL?
13 Febrero 2009, 15:17 PM
buenas, tengo una duda en SQL (no es mi fuerte), tengo la siguiente estructura de árbol:

item pad nombre
1 0 hola
2 0 chau
3 2 schau1
4 2 schau2
5 2 schau3
6 0 quetal
7 1 shola1


me gustaría poder obtenerla ordenada mediante SQL (ya que actualmente lo hacía mediante PHP), algo así:


item pad nombre
1 0 hola
7 1 shola1
2 0 chau
3 2 schau1
4 2 schau2
5 2 schau3
6 0 quetal


pero con la condición que no sea para un determinado motor SQL (trabajo con MSSQL y MySQL)

alguna idea????

S2
#12
PHP / error con hora????
29 Octubre 2008, 20:11 PM
buenas, tengo una duda sobre la configuración de php y el horario del sistema, la cosa es así, soy de argentina y cambiamos el horario a horario de verano, además tengo configurado para que la hora se actualice automáticamente por internet, el tema es que en internet no tienen esta modificación del "horario de verano", entonces cambié mi zona horaria una hora para que "calce", todo funcionaba bien con el sistema e incluso sql, pero ahora descubro que con php no... en php me adelanta 2 horas cuando llamo a la función time(), será un bug o un problema de configuración???

S2

#13
Software / falla en grabación (grabadora DVD)
7 Agosto 2008, 16:14 PM
buenas... tengo una duda que me dejó desconcertado... tenía una grabadora de DVD pionner drw111d que anduvo bien por mucho tiempo, después simplemente empezaron a fallar las grabaciones que hacía (no tiraba ningún error durante la grabación pero al verificar muchísimos), entonces supuse que el laser quemador se había agotado, el tema es que ahora conseguí una segunda grabadora (Sony NEC Optiarc ad-7190A) y para mi asombro tengo el mismo problema, incluso probé cambiando el cable ide, tengo además una grabadora de CD's Benq (sobre el mismo cable), la cual funciona bien y ya tiene muchos años, probé también cambiando mi versión de Nero, (tenía la 8.2.blabla) y volví a la 7.9.6 que leí era mejor pero no logro solucionar el problema... alguno tiene una **** idea de que puede ser???

S2
#14
buenas... se me planteó una duda (aunque no se si es aquí donde debería plantearla), mi duda es con los programas de Windows vista (los que trae por defecto el SO), cuando trato de ejecutarlos sobre XP me dice que no son ejecutables válidos de windows, pero he aquí lo raro, ambas plataformas son de 32 bits, si fuera de 64 sería lógico que no funcionara, pero como es de 32 me quedó la duda que tiene la nueva cabecera de los ejecutables de vista? que se modificó en esta?... haber si alguien tiene una idea... je...  :P

S2
#15
Estaba un poco al dope últimamente y decidí crear este nuevo crackme... en el no hay ninguna ciencia nueva... pero incluye un par de cosas que vi en unos programas que estuve crackeando últimamente... aquí os dejo:

http://h1.ripway.com/karman/Files/crackme2.rar

No creo que sea recomendable para principiantes... pero si quieren pueden echarle un vistazo...

Solucionado por:

x4uth (Keygen y tuto)

S2

PD: "NO PUBLIQUEN CLAVES... MÁNDENMELAS POR PRIVADO Y YO LAS COLOCARÉ AQUÍ"... je

#16
Ingeniería Inversa / Crack Me If You Can by Karman
24 Septiembre 2007, 18:28 PM
Vi que se postearon crack me's, tonces yo tb posteo el mío... haber si lo descifran...  :xD

http://h1.ripway.com/karman/Files/crackme.rar

El que lo descifra se gana una cuenta en mi sitio(??) je  ;D ...

Bueno... me han pedido que aclare: "NO PUBLIQUEN CLAVES... MÁNDENMELAS POR PRIVADO Y LAS COLOCARÉ AQUÍ"... je

Ya lo han resuelto:


1º <~>FeRcHu<~>
2º karmany
3º x4uth
4º _kuka_


haber si alguien más lo descifra...  :P

PD: x4uth me hecho caer en cuenta de un bug en el código que lo hacía relativamente fácil de crackear (no tuve en cuenta la posibilidad de que modifiquen el serial en el registro) así que ahora he solucionado ese problema para que no les sea tan fácil...  :P

S2