jueves, 4 de septiembre de 2008

Wallpaper

CHenry

Veremos aquí, como con un simple programa podremos cambiar el fondo de pantalla de nuestro sistema.

Archivos relacionados

WallPaper.zip

Continuar leyendo

miércoles, 3 de septiembre de 2008

Respuesta al Ejercicio BH 64

José Enrique

He aquí la respuesta que en contró José Enrique para el ejercicio que se publicó en la edición #64.

Archivos relacionados

Respuesta BH 64.zip

Continuar leyendo

martes, 2 de septiembre de 2008

Ejercicio BH 66

Halle todos los números de dos cifras que cumplen las siguientes propiedades:
  • Las cifras de las decenas deben ser 3 unidades menor que las de las unidades.
  • Si ese número se le sustrae al número que se obtiene de invertir sus cifras se obtiene 27.
  • El número debe ser par.

Continuar leyendo

lunes, 1 de septiembre de 2008

Arreglando el registro de Windows

DR3X [lanleyva@infomed.sld.cu]

Cree un archivo .bat ycopie el código a continuación:

echo "Para limpiar el registro de posibles virus"

echo "Eliminar registro de archivos infectados"
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\msconfig.exe" /f
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\regedit.exe" /f
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\regedt32.exe" /f
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\cmd.exe" /f
echo "Reactivar la protección del firewall y protección"
reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List" /v C:\WINDOWS\lsass.exe /f
reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControl001\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List" /v C:\WINDOWS\lsass.exe /f
reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControl002\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List" /v C:\WINDOWS\lsass.exe /f

Echo habilitar farchivos ocultos
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v Hidden /t REG_DWORD /d "00000001" /f

Echo mostrar carpetas y archivos del sistema operativo
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v ShowSuperHidden /t REG_DWORD /d "00000001" /f

Echo habilitar el taskmanager
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System /v DisableTaskmgr /t REG_DWORD /d "00000000" /f

Echo habilitar el editor del registro
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System /v DisableRegistryTools /t REG_DWORD /d "00000000" /f

Echo habilitar opciones de carpeta
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer /v NoFolderOptions /t REG_DWORD /d "00000000" /f

Echo ver las extensiones de los archivos
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v HideFileExt /t REG_DWORD /d "00000000" /f

Echo habilitar la consola (MS-DOS).
REG add HKCU\Software\Policies\Microsoft\Windows\System /v DisableCMD /t REG_DWORD /d "00000000" /f

Continuar leyendo

jueves, 28 de agosto de 2008

Plasma

h0aX [blackhat4all@gmail.com]

Hoy propongo un código para simular efecto plasma dinámicamente con instrucciones matemáticas. No se equieren recursos adicionales o dependencias a archivos de imagenes externos. Podrás encontrar una demostración de la utilización de la clase CPlasma en el archivo relacionado, al final de este artículo.

[Hagamos algo de arte en nuestro monitor]

//CPlasma.h
/****************************************************************************
**
** $Nombre: CPlasma
**
** $Autor: h0aX
**
** $Fecha: 24/agosto/2008
**
** $Descripción: Módulo para generación de texturas dinámicas
** con reproducción de efecto plasma. Este código
** está basado en uno de los demos de Jan Horn (http://www.sulaco.co.za)
**
****************************************************************************/

#ifndef CPlasmaH
#define CPlasmaH

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <glaux.h>
#include <math.h>

typedef struct
{
  BYTE R;
  BYTE G;
  BYTE B;
}
CPixel;

class CPlasma
{
  private:
    GLuint PlasmaTex;
    char *Plasma;
    int Sr[8];
    int Sc[8];
    int sinHalfTable[512];
    int sinOneTable[512];
    int sinTwoTable[512];
    int sinFourTable[512];
    GLuint CreateTexture(int Width, int Height, GLvoid *pData);
  
  public:
    CPlasma();
    ~CPlasma();
    void UpdateTexture();
};

#endif

//CPlasma.cpp
#include "CPlasma.h"

GLuint CPlasma::CreateTexture(int Width, int Height, GLvoid *pData)
{
  GLuint Texture;

  if (NULL == pData)
  {
    MessageBox(NULL, "Error creando texturas", "Plasma Module", MB_ICONERROR);
    return 0;
  }

  glGenTextures(1, &Texture);
  glBindTexture(GL_TEXTURE_2D, Texture);
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexImage2D(GL_TEXTURE_2D, 0, 3, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);

  return Texture;
}

void CPlasma::UpdateTexture()
{
  WORD x[4], xCount[4], y[4], yCount[4];
  int i, j, c;
  CPixel *Pixel;

  for (c=0; c<4; c++)
    y[c] = Sr[c+4];

  for (c=0; c<4; c++)
  {
    xCount[c] = Sc[c];
    yCount[c] = Sc[c+4];
  }

  for (i=0; i<64; i++)
  {
    for (c=0; c<4; c++)
      x[c] = Sr[c];
    for (c=0; c<4; c++)
    {
      xCount[c] = (Sc[c] + i*2) % 512;
      yCount[c] = (Sc[c+4] + i*2) % 512;
    }

    for (j=0; j<64; j++)
    {
      Pixel = (CPixel *)(Plasma + (3*(i*64 + j)));
      Pixel->R=((sinHalfTable[x[0]]+sinOneTable[x[1]]+sinTwoTable[x[2]]+sinFourTable[x[3]])+(sinHalfTable[y[0]]+sinOneTable[y[1]]+sinTwoTable[y[2]]+sinFourTable[y[3]]))>>3;       Pixel->G=((sinHalfTable[x[2]]+sinOneTable[x[3]]+sinTwoTable[x[0]]+sinFourTable[x[1]])+(sinHalfTable[y[2]]+sinOneTable[y[3]]+sinTwoTable[y[0]]+sinFourTable[y[1]]))>>3;
      Pixel->B=((sinHalfTable[x[3]]+sinOneTable[x[0]]+sinTwoTable[x[1]]+sinFourTable[x[2]])+(sinHalfTable[y[1]]+sinOneTable[y[2]]+sinTwoTable[y[3]]+sinFourTable[y[0]]))>>3;
      for (c=0; c<4; c++)
      {
        x[c] = ((x[c] + (sinTwoTable[xCount[c]])/32 -4 + 512)) % 512;
        xCount[c] = (xCount[c] + 2) % 512;
      }
    }

    for (c=0; c<4; c++)
      y[c] = (y[c] + (sinOneTable[yCount[c]])/32 -4 + 512) % 512;
  }

  for (c=0; c<8; c++)
  {
    Sr[c] = (Sr[c] + (sinTwoTable[Sc[c]])/32 -4 + 512) % 512;
    Sc[c] = (Sc[c] + 2) % 512;
  }

  glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, Plasma);
}

CPlasma::CPlasma()
{
  GLfloat temp;
  Plasma = new char[64*64*3];
  memset(Plasma, 255, 64*64*3);
  PlasmaTex = CreateTexture(64, 64, Plasma);
  UpdateTexture();

  for (int i=0; i<8; i++)
  {
    Sr[i] = random(256);
    Sc[i] = Sr[i];
  }

  for (int i=0; i<512; i++)
  {
    temp = 4 * M_PI * i / 512;
    sinHalfTable[i] = (sin(temp/2)*128 + 128);
    sinOneTable[i] = (sin(temp )*128 + 128);
    sinTwoTable[i] = (sin(temp*2)*128 + 128);
    sinFourTable[i] = (sin(temp*4)*128 + 128);
  }
}

CPlasma::~CPlasma()
{
  delete[] Plasma;
}

Archivos relacionados

Plasma.zip

Continuar leyendo

miércoles, 27 de agosto de 2008

Autorun

JKS [jksware@gmail.com]

Se encuentra tras este link, un programa que ayudará a crear esos archivos autoejecutables que a veces tanta falta nos hacen para... bueno, para usarlos, xD

Archivos relacionados

Autorun.zip

Continuar leyendo

martes, 26 de agosto de 2008

Huffman

CHenry [chenry@lab.matcom.uh.cu]

Si de métodos de compreción se trata, entonces sin lugar a duda Huffman tiene ganado ya amplio terreno en este aspecto.

Archivos relacionados

Huffman.zip

 

Continuar leyendo

lunes, 25 de agosto de 2008

Ping a IP por rango

Eddy [delvalle@otepr.co.cu]

Hace algun tiempo en BlackHat presentaron un código que hacía ping a un número restringido de IPs escrito en Python el cual a mí me pareció que se podía mejorar mucho y me dediqué a escribir una versión mejorada que permite hacer ping por rango.


Este código se puede ejecutar de la siguiente manera
En Linux: luego de darle permisos de ejecución, tecleamos en el terminal:
$ ./ipPinger.py 10.208.0.0 10.208.10.5
y el programa hara ping a acada una de las IPs en el rango especificado

En Windows:
> python ipPinger.py 10.208.0.0 10.208.10.5
y se obtiene el mismo resultado

Cualquier duda pueden preguntar sin pena.

#!/usr/bin/env python
import os
import sys

def Acarreo(IP, iByte = 3):
  if iByte == -1:
    return IP
  if IP[iByte] > 255:
    IP[iByte] = 0
    IP[iByte-1] = IP[iByte-1] + 1
    Acarreo(IP, iByte - 1)
  return IP

def GenerarRango(StartIP, EndIP):
  #verificar que StartIP es menor que EndIP
  StartIP = map(int,StartIP.split('.'))
  EndIP = map(int,EndIP.split('.'))
  for i in range(0,4):
        if StartIP[i] > EndIP[i]:
          #swap values
          StartIP , EndIP = EndIP, StartIP
          break
  rango = []
  while not( StartIP[0] == EndIP[0] and \
             StartIP[1] == EndIP[1] and \
             StartIP[2] == EndIP[2] and \
             StartIP[3] == EndIP[3] ):
    #acarreo de suma
    StartIP = Acarreo(StartIP)
    rango.append(str(StartIP[0])+"."+str(StartIP[1])+"."+str(StartIP[2])+"."+str(StartIP[3]))
    StartIP[3] = StartIP[3] + 1
  return rango

for ip in GenerarRango(sys.argv[1],sys.argv[2]):
  os.system("ping "+ip)

Continuar leyendo

martes, 19 de agosto de 2008

Kernel Simple

h0aX [hoax_ws@yahoo.es]

En la edición 43 de este boletín se publicó un código titulado "Mulo-BootLoader" donde se presentaba un boot loader en su estado más simple. Siguiendo la misma praxis probablemente deba nombrar este código "Kernel a lo bestia" o algo parecido, pero por respeto a las bestias me limitaré a llamarlo "Kernel Simple".

Esta vez en nuestro taller de códigos presentaré el primer kernel publicado en BlackHat, tan cubano como inacabado pero muy útil para aquellos que deseen orientación en la utilización de las interrupciones del BIOS como primera línea de fuego en el acceso al hardware de nuestras PCs.

Aclaro que el código va dedicado solo a programadores experimentados en C, con sólidas bases de ensamblador y arquitectura de máquinas 8086. Por falta de tiempo no podría entregarme al placer de escribir un manual del tipo -Comenzando el desarrollo de un kernel-, no obstante estoy dispuesto a compartir gustosamente mi bibliografía con aquellas personas que me hagan saber su interés.

Por último sería injusto dejar de mencionar el sistema ADIX OS de Aditya Kumar Singh como mi principal referencia para este experimento.

[Instalando el kernel en un floppy]
Al final de este artículo encontrarás disponible para su descarga el archivo Calipso.zip. A continuación se describen los pasos a seguir para instalar su contenido.

1 Con una consola del sistema posiciónate en el directorio BOOT
2 Introduce un diskette formateado en la disquetera
3 Ejecuta el siguiente comando en el símbolo del sistema "PC boot12.bin 0 3 –f0" (sin comillas)
4 Ejecuta el siguiente comando en el símbolo del sistema "PC boot12.bin 3e 1c2 –f0 3e"
5 Por último copiamos el kernel al diskette con el comando "COPY ..\Kernel\kernel.bin a:"

Nota: PC.exe es un programa llamado Partial Copy cuya funcionalidad consiste en el copiado de datos raw a disco, de este modo escribimos el bootloader en el sector de arranque inicial del disquette.

Para probar el sistema reinicia el PC con el diskette.

Archivos relacionados

Calipso.zip

Continuar leyendo

Respuesta al Ejercicio BH 63

Eddy [delvalle@otepr.co.cu]

Enunciado:

Hay M soldados en un cerco y tienen un solo caballo. Para salir forman circularmente y comienzan a contar inicialmente por un soldado elegido al azar. Cada N soldados uno sale y el último se queda con el caballo.
Hacer un programa que permita imprimir que soldado saldrá del cerco eon el caballo si se conoce la cantidad de soldados (M) y el incremento (N) en el conteo.

#!/usr/bin/env python
cant_soldados = int(raw_input("Entre la cantidad soldados: "))
iteraciones = int(raw_input("Entre el numero escogido: "))

soldados = range(1, cant_soldados+1)

i = 0
n = 1
while len(soldados) > 1:
if i == len(soldados):
i = 0
if n == iteraciones:
del soldados[i]
n = 1
else:
n = n + 1
i = i + 1

print soldados[0]

Continuar leyendo

Ejercicio BH 64

Confeccione un programa para imprimir todos los números pares de 4 cifras formados por los d¡gitos 0,1,2,3 que cumplan la condición de que los d¡gitos que lo forman no se repitan.

Continuar leyendo

Extraer elementos de tipo específico de una lista

Eddy [delvalle@otepr.co.cu]

Esta es una función a la que se le pasa como parámetro un tipo y una colección, y ella devuelve sólo los elementos que son del tipo que se le pasó como parámetro, este puede ser, por su puesto, una clase definina por ti.
La sección de código bajo la definición de la función es para probar la función con un ejemplo.

#!/usr/bin/env python
def extraerPorTipo(tipo, coleccion):
lista = []
for elemento in coleccion:
if isinstance(elemento, tipo):
lista.append(elemento)
return lista

#esta seccion hace la comprobacion de la función
cadena = "esta es una cadena"
milista = ["asd", 3, "hola", 5.0, 4, cadena]
print "de la lista "+str(milista)+" son de tipo entero:"
print extraerPorTipo(int, milista)
raw_input("presione enter para continuar")

#esto devolvera:
# de la lista ['asd', 3, 'hola', 5.0, 4, 'esta es una cadena'] son de tipo entero:
# [3, 4]

Continuar leyendo

Lupa

CHenry [chenry@lab.matcom.uh.cu]

Windows tiene un programa que hace algo similar, no obstante, nunca está demás ver una réplica de dicha utilidad, más cuando esta ha sido creada por un cubano, miembro de BlackHat y muchísimo más si pone a disposición de todos el código fuente.

/* Escrito por chenry para la comunidad de BH
Compilado con VS2003
*/
#include "stdafx.h"
#include "lupa.h"
#define MAX_LOADSTRING 100

HINSTANCE hInst;
TCHAR szTitle[MAX_LOADSTRING] = "Lupa by chenry for BH";
TCHAR szWindowClass[MAX_LOADSTRING] = "lupa";

ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
  MSG msg;
  HACCEL hAccelTable;

   MyRegisterClass(hInstance);

  if (!InitInstance (hInstance, nCmdShow))
  {
    return FALSE;
  }

  hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_LUPA);

  while (GetMessage(&msg, NULL, 0, 0))
  {
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

  return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
  WNDCLASSEX wcex;

  wcex.cbSize = sizeof(WNDCLASSEX);

  wcex.style = CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc = (WNDPROC)WndProc;
  wcex.cbClsExtra = 0;
  wcex.cbWndExtra = 0;
  wcex.hInstance = hInstance;
  wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_LUPA);
  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wcex.lpszMenuName = (LPCTSTR)IDC_LUPA;
  wcex.lpszClassName = szWindowClass;
  wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

  return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
  HWND hWnd;

  hInst = hInstance; // Store instance handle in our global variable

  hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VSCROLL,
50,50,200,200, NULL, NULL, hInstance, NULL);

  if (!hWnd)
  {
    return FALSE;
  }

  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);

  return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  int wmId, wmEvent;
  PAINTSTRUCT ps;

  HDC hdc,hdcDesktop;
  static RECT paintRect;

  RECT clientRect;
  POINT punto;

  static bool isPainting;
  SCROLLINFO scroll;

  static int zoom;
  static bool onTimer=false;

  switch (message)
  {
    case WM_VSCROLL:
    {
      GetClientRect(hWnd,&clientRect);
      switch (LOWORD(wParam))
      {
        case SB_LINEUP:
        {
          if(zoom>1&&zoom<6)
          {
            zoom = zoom - 1;
            SetScrollPos(hWnd,SB_VERT,(zoom -1) * clientRect.bottom/5,TRUE);
          }
          return 0;
        }
        case SB_LINEDOWN:
        {
          if(zoom>0&&zoom<5)
          {
            zoom = zoom + 1;
            SetScrollPos(hWnd,SB_VERT,(zoom -1) * clientRect.bottom/5,TRUE);
          }
          return 0;
        }
      }

      return 0;
    }
    case WM_SIZE:
    {
      GetClientRect(hWnd,&clientRect);
      scroll.cbSize = sizeof(SCROLLINFO);
      scroll.fMask = SIF_ALL;
      scroll.nMin = 0;
      scroll.nMax = clientRect.bottom;
      scroll.nPage = clientRect.bottom/5;
      scroll.nPos = (zoom -1) * clientRect.bottom/5;
      SetScrollInfo(hWnd,SB_VERT,&scroll,TRUE);
      return 0;
    }
    case WM_LBUTTONDOWN:
    {
      hdcDesktop = GetDC(NULL);
      SetROP2(hdcDesktop, R2_NOT);

      Rectangle(hdcDesktop,paintRect.left,paintRect.top,paintRect.right,paintRect.bottom);
      DeleteDC(hdcDesktop);

      SetCapture(hWnd);
      isPainting = true;
      onTimer=false;

      return 0;
    }
    case WM_LBUTTONUP:
    {
      hdcDesktop = GetDC(NULL);
      SetROP2(hdcDesktop, R2_NOT);
      Rectangle(hdcDesktop,paintRect.left,paintRect.top,paintRect.right,paintRect.bottom);
      DeleteDC(hdcDesktop);

      InvalidateRect(hWnd,NULL,true);

      ReleaseCapture();
      isPainting = false;
      onTimer=true;

      return 0;
    }

    case WM_MOUSEMOVE:
    {
      if(isPainting)
      {
        GetCursorPos(&punto);

        hdcDesktop = GetDC(NULL);
        SetROP2(hdcDesktop, R2_NOT);
        Rectangle(hdcDesktop,paintRect.left,paintRect.top,paintRect.right,paintRect.bottom);
        DeleteDC(hdcDesktop);

        GetClientRect(hWnd,&clientRect);

        paintRect.left = punto.x - (clientRect.right - clientRect.left)/(2*zoom);
        paintRect.right = punto.x + (clientRect.right - clientRect.left)/(2*zoom);
        paintRect.top = punto.y - (clientRect.bottom - clientRect.top)/(2*zoom);
        paintRect.bottom = punto.y + (clientRect.bottom - clientRect.top)/(2*zoom);

        hdcDesktop = GetDC(NULL);
        SetROP2(hdcDesktop, R2_NOT);

        Rectangle(hdcDesktop,paintRect.left,paintRect.top,paintRect.right,paintRect.bottom);
        DeleteDC(hdcDesktop);

        InvalidateRect(hWnd,NULL,true);
      }
      return 0;
    }
    case WM_CREATE:
    {
      zoom = 5;
      GetClientRect(hWnd,&clientRect);
      scroll.cbSize = sizeof(SCROLLINFO);
      scroll.fMask = SIF_ALL;
      scroll.nMin = 0;
      scroll.nMax = clientRect.bottom;
      scroll.nPage = clientRect.bottom/5;
      scroll.nPos = (zoom -1) * clientRect.bottom/5;;
      SetScrollInfo(hWnd,SB_VERT,&scroll,TRUE);

      isPainting = false;
      SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
      SetTimer(hWnd,1,100,NULL);
      return 0;
    }
    case WM_TIMER:
    {
      if(onTimer)
      {
        hdc = GetDC(hWnd);

        hdcDesktop = GetDC(NULL);
        GetClientRect(hWnd,&clientRect);
        if(isPainting)
        StretchBlt(hdc,clientRect.left,clientRect.top,(clientRect.right - clientRect.left),(clientRect.bottom - clientRect.top),hdcDesktop,paintRect.left,paintRect.top,(paintRect.right - paintRect.left),(paintRect.bottom - paintRect.top),SRCINVERT);
        else
StretchBlt(hdc,clientRect.left,clientRect.top,(clientRect.right - clientRect.left),(clientRect.bottom - clientRect.top),hdcDesktop,paintRect.left,paintRect.top,(paintRect.right - paintRect.left),(paintRect.bottom - paintRect.top),SRCCOPY);

        DeleteDC(hdcDesktop);

        ReleaseDC(hWnd,hdc);

      }
      return 0;
    }
    case WM_COMMAND:
    {
      wmId = LOWORD(wParam);
      wmEvent = HIWORD(wParam);

// Parse the menu selections:
      switch (wmId)
      {
        case IDM_EXIT:
        DestroyWindow(hWnd);
        return 0;
        default:
        return DefWindowProc(hWnd, message, wParam, lParam);
      }
      return 0;
    }
    case WM_PAINT:
    {
      hdc = BeginPaint(hWnd, &ps);

      hdcDesktop = GetDC(NULL);
      GetClientRect(hWnd,&clientRect);
      if(isPainting)
      StretchBlt(hdc,clientRect.left,clientRect.top,(clientRect.right - clientRect.left),(clientRect.bottom - clientRect.top),hdcDesktop,paintRect.left,paintRect.top,(paintRect.right - paintRect.left),(paintRect.bottom - paintRect.top),SRCINVERT);
      else
      StretchBlt(hdc,clientRect.left,clientRect.top,(clientRect.right - clientRect.left),(clientRect.bottom - clientRect.top),hdcDesktop,paintRect.left,paintRect.top,(paintRect.right - paintRect.left),(paintRect.bottom - paintRect.top),SRCCOPY);

      DeleteDC(hdcDesktop);

      EndPaint(hWnd, &ps);
      return 0;
    }
    case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }
    default:
    return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}

void DrawBoxOutline (HWND hwnd, RECT rect)
{
  HDC hdc ;
  hdc = GetDC (NULL) ;
  SetROP2 (hdc, R2_NOT) ;
  SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
  Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
  ReleaseDC (hwnd, hdc) ;
}

Archivos relacionados

Lupa.zip

Continuar leyendo

lunes, 11 de agosto de 2008

Respuesta al Ejercicio BH 59

thunder [yuniet02015@hab.jovenclub.cu]

Ejercicio:
==========
Los números 46 y 96 tienen una curiosa propiedad, su producto no se altera aunque las cifras que lo integran cambien de lugar.
46 * 96 = 4416
64 * 69 = 4416
Confeccione un programa para imprimir todos los números de dos cifras que cumplen esta propiedad.



'=========================================
'= Respuesta en Visual Basic =
'= al pequeño ejercicio =
'= de la edicion #59 =
'= de la revista =
'= BlackHat =
'=========================================

Private Sub Command1_Click()
  On Error Resume Next

  For a = 9 To 98
    num1 = a + 1
    rev1 = StrReverse(num1)
    For i = 9 To 98
      num2 = i + 1
      result1 = num1 * num2
      rev2 = StrReverse(num2)
      result2 = rev1 * rev2

      If result1 = result2 Then
        Text1.Text = Text1.Text + Str(num1) + " -" + Str(num2) + vbCrLf
        c = c + 1
        Label2.Caption = c
      End If

    Next
  Next

End Sub

Private Sub Command2_Click()
  Text1.Text = ""
  Label2.Caption = ""
  Command1.SetFocus
End Sub

Archivos relacionados

Respuesta.zip

Continuar leyendo

Cut File

Alien [blackhat4all@gmail.com]

Este código no es ni será catalogado como la gran invención del año, pero si puede ser de utilidad para muchos que quieran meter en un dispositivo de poca capacidad un archivo de audio o video que supera el tamaño de la unidad en la que se quiere introducir.

CLS
'Definimos el buffer, que no es más que la cantidad de bites que serán leídos en cada pasada.
'Mientras mayor sea el buffer más rápido terminará
DIM buffer AS STRING * 32000
OPEN ("k:\nuevo\a.dat") FOR BINARY AS #1
  OPEN ("c:\b.dat") FOR BINARY AS #2

'Hacemos un ciclo hasta la cantidad de Megas que queremos copiar (en este caso son 490 Mb)
    FOR i = 1 TO 490 * 1048576 STEP 32000
      GET #1, i, buffer
      PUT #2, i, buffer

'Nos paramos en la primera línea y mostramos el progreso...
      LOCATE 1, 1
      PRINT "Guardando: "; INT(i / 1048576); " Mb"
    NEXT
  CLOSE #2
CLOSE #1


Sabiendo de antemano que un archivo de audio o video puede funcionar aún faltandole parte de este, este código lo que hace en sí es definir un tamaño (siempre menor que el del archivo) y empezar a copiar hasta que se llegue a ese tamaño. En este caso el tamaño definido es de 490 Mb. Al terminar, se tendrá solo la primera parte del archivo hasta que este llegue al tamaño especificado.

Si se sabe el tamaño de la cabecera del archivo, se pudiera hacer un programa que, en lugar de solo llevar a parte los primeros x Mb del archivo, divida al mismo en varios pedazos, pero bueno, eso será en otra edición xD.

Continuar leyendo

Geometry.cpp

Alex17 [marisolriech@infomed.sld.cu]

Es este un interesante código que le dará la posibilidad a los que logren dominarlo de hacer algunas otras cositas con el trabajo de los discos duros.

// Get Disk Geometry.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

DISK_GEOMETRY SupportedGeometry[20];
DWORD SupportedGeometryCount;

VOID
GetSupportedGeometrys(HANDLE hDisk)
{
  DWORD ReturnedByteCount;

  if(DeviceIoControl(hDisk,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,SupportedGeometry,sizeof(SupportedGeometry),&ReturnedByteCount,NULL))
    SupportedGeometryCount = ReturnedByteCount / sizeof(DISK_GEOMETRY);

  else
    SupportedGeometryCount = 0;
}

VOID
PrintGeometry( PDISK_GEOMETRY lpGeometry )
{
  LPSTR MediaType;

  switch ( lpGeometry->MediaType )
  {
    case F5_1Pt2_512:
      MediaType = "5.25, 1.2MB, 512 bytes/sector";
    break;
    case F3_1Pt44_512:
      MediaType = "3.5, 1.44MB, 512 bytes/sector";
    break;
    case F3_2Pt88_512:
      MediaType = "3.5, 2.88MB, 512 bytes/sector";
    break;
    case F3_20Pt8_512:
      MediaType = "3.5, 20.8MB, 512 bytes/sector";
    break;
    case F3_720_512:
      MediaType = "3.5, 720KB, 512 bytes/sector";
    break;
    case F5_360_512:
      MediaType = "5.25, 360KB, 512 bytes/sector";
    break;
    case F5_320_512:
      MediaType = "5.25, 320KB, 512 bytes/sector";
    break;
    case F5_320_1024:
      MediaType = "5.25, 320KB, 1024 bytes/sector";
    break;
    case F5_180_512:
      MediaType = "5.25, 180KB, 512 bytes/sector";
    break;
    case F5_160_512:
      MediaType = "5.25, 160KB, 512 bytes/sector";
    break;
    case RemovableMedia:
      MediaType = "Removable media other than floppy";
    break;
    case FixedMedia:
      MediaType = "Fixed hard disk media";
    break;
    default:
      MediaType = "Unknown";
    break;
  }
  printf(" Media Type: %s\n", MediaType );
  printf("Cylinders%d,Tracks/Cylinder%d,Sectors/Track%d\n",lpGeometry->Cylinders.LowPart,lpGeometry->TracksPerCylinder,lpGeometry->SectorsPerTrac); }

int main(int argc, char* argv[])
{
  HANDLE hDrive;
  UINT i;

  hDrive = CreateFile(
"\\\\.\\C:",
  0,
  FILE_SHARE_READ,
  NULL,
  OPEN_ALWAYS,
  0,
  NULL);
  if (hDrive == INVALID_HANDLE_VALUE)
  {
    printf( "Open failed: %d\n", GetLastError());
    ExitProcess(1);
  }

  GetSupportedGeometrys( hDrive );
  printf( "\nDrive C supports the following disk geometries\n" );
  for( i=0; i<SupportedGeometryCount; i++ )
  {
    printf("\n");
    PrintGeometry (&SupportedGeometry[i]);
  }
  printf("\n");
  system ("pause");
  return 0;
}

Continuar leyendo

RenderToTexture

h0aX [hoax_ws@yahoo.es]

A raíz de un magnifico artículo publicado por JKS titulado "Retorno al 3D" y de una confusión igualmente excelsa en imaginación y en derroches de especulaciones he recibido varios correos sobre mi supuesto "motor 3D para shooters".

Todo aquel que me conoce en el plano personal sabe que padezco de un laconismo con tendencias al aburrimiento que resulta especialmente irascible para aquellos amantes y fieles emprendedores de las opiniones insulsas y los comentarios ramplones. Lo cierto es que me desagrada la controversia a menos que me sea producente, así que me limitaré a decir justo lo que requiere ser sabido y no complaceré a nadie con una palabra de más. Quisiera que por favor se prestara especial atención a la oración que a esta precede para así ahorrarme el trabajo de responder algunos correos que últimamente estoy recibiendo. Yo NO estoy haciendo un motor 3D para juego alguno, el framework 3D que me he fabricado sobre OpenGL (y que algunos beodos artistas se han empeñado en pintar como "motor 3D") es solo una herramienta con "fines experimentales" que ni por mucho está pensada para quedar ensamblada como un entumecedor de cerebros somnolientos, verbigracia, un adocenado juego para niñitos aburridos. El objetivo de mis trabajos extraoficiales con gráficos generados (que ya parece haberse hecho público de la peor manera posible) está mucho más vinculado con la investigación científica y sus resultados están enfocados en disímiles temáticas: diseño de nuevos dispositivos de control de interfaces 3D, simulación de elementos mecánicos vinculados a la robótica, simulación de sistemas físicos, etc. Mi motivación por el desarrollo de juegos no va más allá de mis horas de extenuación en que dispongo algún que otro elemento simple de mis sistemas de modo "juguetón", como el estudiante del MIT que aburrido hace un circuito para una cajita de música y se lo obsequia a su novia. Aclarada la duda, todo aquel que tenga interés en explotar el 3D como herramienta de trabajo puede escribirme y de ello intercambiaremos toda la información que desee. En cambio, aquel cuya intención fundamental es sentarse a desarrollar juegos, aquí les va un consejo: Usen DirectX, yo he tenido oportunidad de trabajar con tan exquisita API y les garantizo que para hacer juegos es la ideal. Mientras en OpenGL debes sentarte a pensar el -cómo hacer- en DirectX solo deberás pensar en -qué hacer- porque todo esta dispuesto justo para ese propósito, la creación de entumecedores de mentes. Creo que con esto quedan más que contestadas las dudas de la comunidad, aunque aún quisiera responder a nivel personal esta pregunta:
- ¿Por qué no usas un motor ya hecho?

No lo uso porque me desagradaría hacerlo, y me desagradaría por la misma razón que me desagradan los lenguajes scripts e interpretados. Aprecio a un programador por la manera que hace uso del control que el lenguaje pone en sus manos. Yo disfruto tiranizar estos aparatos electrónicos con sentencias C++ escritas con tal organización que parezcan un soneto de Quevedo... ese es mi hobby. No obstante cuando me piden un trabajo en PHP, jamás me he dispuesto a programar mi propia aplicación servidora en C++, en vez de eso he sabido agradecer las bondades del lenguaje que para esas nimiedades me ha sido ofrecido. Llegará el momento en que el desarrollo de un juego solo requiera alta destreza con el botón Siguiente y el Atrás, será ese el pináculo del desarrollo de la industria de video juegos, pero mientras de placer se trate, seguirá h0aX escribiendo sonetos en C++;

¿Qué captas, noturnal, en tus canciones,
Góngora bobo, con crepusculallas,
si cuando anhelas más garcivolallas
las reptilizas más y subterpones?

[El demo]

Hoy les propongo un demo en el que estuve experimentando las curiosas aplicaciones de la función glCopyTexImage2D para renderizar la escena en una textura dinámicamente :o.

Por último aclararé que nadie debe suponer por mis opiniones aquí expresadas que sea yo un retractor de los video juegos (solo de su uso excesivo) y no debe ningún curioso sorprenderse al encontrar en mis demos alguna evidentísima referencia a PerfectDark, GoldenEye o Zelda de Nintendo64, pues fueron estos los títulos clásicos que coincidieron con mi etapa de jugador.

Solo me resta agradecer a Shiika de #Hero por permitirme usar sus bellos ojos en el diseño de mis demencias tridimensionales. (Pss, a que no me equivoqué)

[Rendimiento]

En aras de conseguir el máximo de rendimiento para cada máquina he definido algunas opciones con las que se pueden cargar la aplicación.

Para definir el nivel de detalles del viewport de las cámaras puedes llamar el programa con una de las siguientes opciones en la línea de comandos:

-VERY_HIGH_QUALITY
-HIGH_QUALITY
-MEDIUM_QUALITY
-LOW_QUALITY
-VERY_LOW_QUALITY

ej: "rtt.exe -MEDIUM_QUALITY"

Para visualizar el demo a pantalla completa se debe usar el parámetro "-fullscreen", ej: "rtt.exe -fullscreen".

No sobra aclarar que esta vez he agregado un limitador de frames para mantener los FPS por los 60. De este modo el programa deberá correr a la misma velocidad con una ATI de 128 que con una de 1024. Pensando siempre en el poco tiempo que tuve para debugear dicho limitador, cualquiera a quien le de problemas puede desactivarlo con el parámetro "-NoFPSLimiter", ej: "rtt.exe -NoFPSLimiter".

Acta est fabula.

Archivos relacionados

RenderToTexture.zip

Continuar leyendo

lunes, 28 de julio de 2008

Ejercicio BH 62

Confeccione un programa que muestre visualmente una pelota rebotando en los bordes de la pantalla.

Continuar leyendo

Instrucciones del procesador matemático

h0aX [hoax_ws@yahoo.es]

Me ha pasado muchas veces mientras uso APIs de OpenGL o DirectX, donde un bucle demasiado grande y con muchas llamadas a funciones matemáticas hacen toda la diferencia y llegan a definir si tu programa correrá en un PIII o no.

Cuando te enfrentas por primera vez a este tipo de problemas te das cuenta que funciones matemáticas de la librería MATH.H que haz usado durante años ya no te parecen tan eficientes. Pero ¿de qué manera podría escribir funciones más rápidas que las definidas en MATH.H? Lo primero que me vino a la mente fue reescribir funciones como sin() y sqrt() (que eran unas de las que más problemas me daban en bucles grandes), pero rehacerlas esta vez en ensamblador. Para ello tuve que recurrir a las instrucciones del procesador matemático. El resultado es notable, principalmente cuando se usa recursividad o bucles.

//Seno
Extended mysin(Extended X)
{
  asm
  {
    FLD X
    FSIN
    FWAIT
  }
}

//Coseno
Extended mycos(Extended X)
{
  asm
  {
    FLD X
    FCOS
    FWAIT
  }
}

//Raíz cuadrada
Extended mysqrt(Extended X)
{
  asm
  {
    FLD X
    FSQRT
    FWAIT
  }
}

Continuar leyendo

Atom

h0aX [hoax_ws@yahoo.es]

Quizás a simple vista no parezca nada sugerente este código, pero sabiendo que es de h0aX, que contiene trabajo con OpenGL y que h0aX es el de mayor rango en BlackHat, de seguro se vuelve un código más que interesante para muchos.

Archivos relacionados

Atom.zip

 

Continuar leyendo

Stream

BoY^```tArEcCOo``` [dainierdbehar@infomed.sld.cu]

ALGO MUY IMPORTANTE ES QUE DEBES TENER INSTALADO EL SITEMA DE FICHEROS NTFS .,., !!

Estos son los comandos para realizar esta tecnica...

Para los new y los que no son tan new pero que se han distanciado un poco de windows para habitar en la shell de UNIX :-/

Version --- Microsoft Windows XP [Version 5.1.2600] (la kk q tengo y con la cual me pincha)

1- Creamos una carpeta,Yo en particular la creare en la unidad "D:" Abrimos la ventanita negra y nos vamos para la famosa letrica... estando ya en la unidad selecionada sea d,h,etc pues continuamos

2- Creamos el directorio o carpeta Este directorio lo creamos con"md" ,ejemplo., si queremos crear una carpeta nombrada xXx, pues escribimos algo como esto "md xXx" sin las comillas ok .., nos asomamos para asegurarnos que la carpeta ha sido creada. con "dir" buscamos dentro y de seguro ahi estara.,.,.

Un tercer paso sera la creacion del txt dentro de la carpeta que nos hicimos...

3- Creando el archivo de texto Para crear este archivo entraremos en la carpeta que creamos llamada "xXx" bueno entramos con el comando "cd" seria"cd xXx" dentro escribimos "echo programa>stream.txt" ya con esto creamos el archivo de texto stream y dentro de este estara escrito programa, no es necesario escribir nada pero lo hago solo para no perderme y saber que programa estara oculto. ejemplo,., programa=programa_real, es decir escribo el nombre real del programa que voy a guardar ,.,"echo superworms>stream.txt" en caso de que quiera ocultar en este txt mi programa superworms (sin comentarios)

Vamos a ver que fue lo que hicimos hasta ahora paso a paso

======================
= PASOS =
======================
1- C:\Documents and Settings\macro>D:
2- D:\>md xXx
3- D:\>dir
El volumen de la unidad D es Almacen
El numero de serie del volumen es: T3NG0-H4M8r3

Directorio de D:\

20/06/2008 22:17 <DIR> kkfuak
09/07/2008 22:25 <DIR> oficoda
30/06/2008 15:09 <DIR> kookies atrevidas
11/07/2008 21:52 <DIR> xXx
0archivos 0bytes
4 dirs 55.55.55 bytes libres
D:\>cd xXx
D:\xXx>echo superworms>stream.txt
D:\xXx>dir

y ahi estara el txt y todo listo para el proximo paso

====================
= OCULTO =
====================
Vamos a ocultar un ejecutable en este caso, pero antes tienes que agarrar el .exe que quieras ocultar dentro del txt y copiarlo en la carpeta que creamos juntico con el txt,. ya copiado ahi pues le damos al siguiente comando -->
"type superworms.exe>stream.txt:oculto.exe"

que fue lo que hicimos?, pues lo que acabamos de hacer fue streaming, es decir meter el programa superworms.exe dentro del fichero stream.txt, y el oculto ese que vez es solo el nombre asociado que le di pa tener referencias a la hora de extraer (algo asi)

Oye algo importante,. todo esto es paso a paso desde que abres la consola hasta que llegues aqui, una cosa detras de otra,. de todos modos tratare de mandar unas fotos aunque creo que no hace falta pero igual las mando...(no mejor no las mando)

Lo que viene sera borrar el programa, pues ya esta dentro del txt y esto lo ejecutamos con "del" ,.,., "del superworms.exe"

Toca por fin sacarlo a la luz pa hacernos kk de la alegria con la siguiente linea de comandos
"start .\stream.txt:oculto.exe"

y finish.... el nombre asociado es el que te de la gana nada varia con eso,. pero si lo que quieres es guardar un video y no un exe pues le tienes que poner la extension al nombre asociado ,. si mi superworms no fuese un ejecutable y si un archivo de video etx el nombre asociado seria oculto.avi
"type superworms.avi>stream.txt:oculto.avi"
"start .\stream.txt:oculto.avi"
bytex

Archivos relacionados

Stream.zip

Continuar leyendo

Pix2Art

JKS [jksware@gmail.com]

Una muy últil aplicacción creada por JKS es ahora compartida para todos los miembros de BlackHat. Un programa que permitirá a los que lo usen convertir imágenes bmp en una seríe de caracteres ASCII.

Archivos relacionados

Pix2Art.zip

 

Continuar leyendo

lunes, 21 de julio de 2008

Ejercicio BH 61

Consideremos un antiguo problema creado por Fibonacci o Leonardo de Pisa matemático italiano de la edad media. Se precisa conocer el número de parejas de conejos adulto resultantes de una pareja durante X meses si cada pareja adulta produce mensualmente una nueva pareja y los recien nacidos alcanzan su plena madures en el curso de un mes. NOTA: Al comenzar se contaba con una pareja de adultos.

Continuar leyendo

Validar e-mail en JavaScript

L1nk [l1nk.darck@gmail.com]

Este Script valida la entrada de una dirección de correo, si es correcta deja continuar con la ejecución del programa y si no, nos dará un mensaje de error, pidiendo entrar de nuevo la dirección del e-mail.
Comprueba que haya un nombre antes de la @, que esta exista y que después de ella haya un nombre, un punto y dos o tres caracteres (.es, .com, .net, etc.…)

Nota: Este código puede ser insertado libremente en cualquier Web.

<HTML>
  <HEAD>
  </HEAD>
  <BODY>
    <SCRIPT LANGUAGE="JavaScript">
      function isEmailAddress(theElement, nombre_del_elemento )
      {
        var s = theElement.value;
        var filter=/^[A-Za-z][A-Za-z0-9_]*@[A-Za-z0-9_]+\.[A-Za-z0-9_.]+[A-za-z]$/;
        if (s.length == 0 ) return true;
        if (filter.test(s))
          return true;
        else
          alert("Entre una dirección de corre valida");
          theElement.focus();
          return false;
      }
    </SCRIPT>
    <FORM><INPUT TYPE="text" NAME="TextField">
    <INPUT TYPE="submit" VALUE="Ejecutar"
ONCLICK="return isEmailAddress(TextField,'TextField' )"> </FORM></BODY>
  </HTML>

Continuar leyendo

Aumentando nuestra privacidad

Alix [aacg@sum.upr.edu.cu]

Una de las grandes novedades que nos trae Firefox 3 es la nueva barra de direcciones más poderosa e inteligente. Esta es capaz de predecir a que URL queremos acceder con solo presionar unas pocas teclas, tomando como referencia nuestro historial de navegación, sitios favoritos (bookmarks), títulos de páginas visitadas, etc. Ya no hace falta escribir direcciones URLs completas, la nueva barra tratara de adivinar a que sitio queremos acceder a medida que tecleamos la dirección del mismo.


Pero que pasaría si compartimos nuestro navegador con otras personas o si alguien utiliza casualmente nuestra PC y no queremos que se enteren de que visitamos “ciertos sitios”. En ese caso lo que debemos hacer es deshabilitar la barra haciendo lo siguiente:

1. En la barra de direcciones escribimos about:config
2. Establecemos el parámetro browser.urlbar.matchonlytyped en True
3. Reiniciamos Firefox

¡Listo!

Ahora les recomendaría limpiar el historial de navegación: Abrimos el menú Herramientas > Opciones y nos dirigimos a la pestaña Privacidad, hacemos click en el botón [Limpiar ahora…] y luego en [Limpiar datos privados ahora] para eliminar cualquier rastro que nos vincule con lo que no queremos que se sepa.

Continuar leyendo

Panel de Control

El friki [yeran@ipipr.rimed.cu]

No en todo momento tenemos acceso al panel de control de nuestra maquina por causa de restricciones o configuración. Una forma de tener acceso a este es mediante la función Shgetspecialfolderlocation que brinda Delphi. Para la programación de esta necesitamos capturar diferentes procesos del sistema. A continuación se muestra una Unit de código de ejemplo.

//Programa que muestra el Panel de Control...
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,ShellApi , ShlObj, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{
  Private declarations
}
public
{
  Public declarations
}
end;

var
Form1: TForm1;
PIDL : PitemIdlist;
Info : Tshellexecuteinfo;
PInfo : Pshellexecuteinfo;
Waitcode : DWord;
implementation
{
  $R *.dfm
}
procedure TForm1.Button1Click(Sender: TObject);
begin
  Shgetspecialfolderlocation(Handle,CSIDL_CONTROLS,PIDL);
  PInfo := @Info;
  with Info do
  begin
    Cbsize := sizeof(Info);
    Fmask := see_mask_nocloseprocess+ see_mask_idlist;
    Wnd := handle;
    Lpverb := nil;
    Lpfile := nil;
    Lpdirectory := nil;
    Nshow:=SW_NORMAL;
    Hinstapp:=0;
    Lpidlist:=PIDL;
  end;
  ShellexecuteEx(PInfo);
  repeat Waitcode:=waitforsingleobject(Info.hprocess,500);
  Application.ProcessMessages;
  until (Waitcode<>Wait_timeout);
end;
end

Continuar leyendo

FunnyNewton

h0aX [hoax_ws@yahoo.es]

Un interesante código que nos permitirá gastarle una buena broma a un amigo. Tengase en cuenta que lo más importante aqui no es el programa en si, sino el código que tras este se encuentra.

Archivos relacionados

FunnyNewton.zip

Continuar leyendo