sexta-feira, 20 de setembro de 2013

Entenda o Formato PE, o formato dos executáveis

Aprendi que a melhor forma de aprender é ensinando (né professor Pachecão?), que realmente é verdade, pois já apliquei essa técnica aprendendo química.

O assunto dessa vez será o formato de arquivos objetos e executáveis voltado para Windows 32bits (originado do Unix COFF) o PE (Portable Executable). Dando atenção ao fato que não sou nenhum expert no assunto, portanto pode haver inconsistência ou invalidez no texto redigito, portanto leia por conta e risco.

P: Gilson, porque seu interesse nesse assunto?
R: Eu sempre aprendi de acordo com a necessidade, nunca precisei saber do formato PE para executar minhas aplicações ou aplicar patchs aos softwares. Mas dessa vez, ao fazer um speed hack para um jogo procurei uma alternativa de sempre procurar os endereços das funções para substituir (como o jogo sofre constantes atualizações), assim teria uma dll estável e sem a necessidade de atualizá-la cada vez que o jogo passasse por um update.

Vamos lá.

Um arquivo PE é formado por blocos de códigos, abaixo mostrei os blocos, suas estruturas e tentarei descrever cada parte para um melhor entendimento.

O Windows tem seu system loader que é encarregado de pôr o arquivo na memória, verificar os blocos, resolver endereços, importar e exportar funções caso os tenha. HMODULE é o nome dado quando o arquivo vai pra memória nossos módulos.

Primeiro temos o DOS Header (IMAGE_DOS_HEADER) constituído de 64 bytes, segue a estrutura:

struct _IMAGE_DOS_HEADER {
    WORD e_magic;
    WORD e_cblp;
    WORD e_cp;
    WORD e_crlc;
    WORD e_cparhdr;
    WORD e_minalloc;
    WORD e_maxalloc;
    WORD e_ss;
    WORD e_sp;
    WORD e_csum;
    WORD e_ip;
    WORD e_cs;
    WORD e_lfarlc;
    WORD e_ovno;
    WORD e_res[4];
    WORD e_oemid;
    WORD e_oeminfo;
    WORD e_res2[10];
    DWORD e_lfanew;
};

e_magic – assinatura MZ (0x4D5A)
e_cblp – tamanho da última página
e_cp – total de página
e_crlc – itens de realocação
e_cparhdr – tamanho do cabeçalho
e_minalloc – tamanho mínimo de memória
e_maxalloc – tamanho máximo de memória
e_ss – valor inicial do registrador SS (Stack Segment)
e_sp – valor inicial do registrador SP (Stack Pointer)
e_csum – checksum do cabeçalho
e_ip – valor inicial do registrador IP (Instruction Pointer)
e_cs – valor inicial do registrador CS (Code Segment)
e_lfarlc – offset (distância) do fragmento stub
e_ovno – overlay
e_res[4] - bytes reservados
e_oemid – identificador OEM
e_oeminfo – informações OEM
e_res2[10] - bytes reservados
e_lfanew – offset do cabeçalho do arquivo PE

O e_lfarlc, esse fragmento é executado caso arquivo PE não possa ser executado. Consiste num número muito pequeno de bytes com instruções, assim ao carregar o arquivo na memória é verificado se é compatível com o sistema, caso não seja essa sessão é executada.

Continuando temos o bloco NT Header (IMAGE_NT_HEADERS) contendo File Header (IMAGE_FILE_HEADER) e Optional Header (IMAGE_OPTIONAL_HEADER).

struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS;

Signature – Assinatura do cabeçalho PE
FileHeader – Estrutura IMAGE_FILE_HEADER
OptionalHeader – Estrutura IMAGE_OPTIONAL_HEADER32

struct _IMAGE_FILE_HEADER {
    WORD Machine;
    WORD NumberOfSections;
    DWORD TimeDateStamp;
    DWORD PointerToSymbolTable;
    DWORD NumberOfSymbols;
    WORD SizeOfOptionalHeader;
    WORD Characteristics;
} IMAGE_FILE_HEADER;

Machine – Tipo de plataforma prevista pra rodar o executável
NumberOfSections – Número de seções apos o cabeçalho
TimeDateStamp – Data e hora de criação do arquivo
PointerToSymbolTable – Ponteiro para tabela de símbolos
NumberOfSymbols – Número de símbolos
SizeOfOptionalHeader – Tamanho do cabeçalho opcional
Characteristics – Características (Flags) do arquivo.

struct _IMAGE_OPTIONAL_HEADER {
    WORD Magic;
    BYTE MajorLinkerVersion;
    BYTE MinorLinkerVersion;
    DWORD SizeOfCode;
    DWORD SizeOfInitializedData;
    DWORD SizeOfUninitializedData;
    DWORD AddressOfEntryPoint;
    DWORD BaseOfCode;
    DWORD BaseOfData;
    DWORD ImageBase;
    DWORD SectionAlignment;
    DWORD FileAlignment;
    WORD MajorOperatingSystemVersion;
    WORD MinorOperatingSystemVersion;
    WORD MajorImageVersion;
    WORD MinorImageVersion;
    WORD MajorSubsystemVersion;
    WORD MinorSubsystemVersion;
    DWORD Win32VersionValue;
    DWORD SizeOfImage;
    DWORD SizeOfHeaders;
    DWORD CheckSum;
    WORD Subsystem;
    WORD DllCharacteristics;
    DWORD SizeOfStackReserve;
    DWORD SizeOfStackCommit;
    DWORD SizeOfHeapReserve;
    DWORD SizeOfHeapCommit;
    DWORD LoaderFlags;
    DWORD NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32;

Magic – Especifica o tipo de arquivo (0x010B executável, 0x0107 imagem rom)
MajorLinkerVersion – versão maior do linker
MinorLinkerVersion – versão menor do linker
SizeOfCode – tamanho do código executável
SizeOfInitializedData – tamanho do bloco de dados de inicialização (Data Segment)
SizeOfUninitializedData – tamanho do bloco de dados não inicializados (BSS Segment)
AddressOfEntryPoint – endereço do ponto de inicialização (RVA)
BaseOfCode – base de código
BaseOfData – base de dados
ImageBase – endereço de mapeamento (preferencial)
SectionAlignment – alinhamento da seção na memória RAM
FileAlignment – alinhamento da seção do arquivo em disco
MajorOperatingSystemVersion – versão maior esperada do sistema operacional
MinorOperatingSystemVersion – versão mínima esperada do sistema operacional
MajorImageVersion – versão máxima do arquivo
MinorImageVersion – versão mínima do arquivo
MajorSubsystemVersion – versão máxima do subsistema esperado
MinorSubsystemVersion – versão mínima do subsistema esperado
Win32VersionValue – versão do win32
SizeOfImage – tamanho da imagem somando os cabeçalhos e seções
SizeOfHeaders – tamanho dos cabeçalhos
CheckSum – checksum do arquivo
Subsystem – subsistema requerido
DllCharacteristics – Características (Flags) das DLLs
SizeOfStackReserve – tamanho reservado do da pilha stack
SizeOfStackCommit – tamanho inicial da pilha salva
SizeOfHeapReserve – tamanho reservado aos heaps
SizeOfHeapCommit – tamanho inicial do heap salvo
LoaderFlags – Parâmetros (Flags) para o carregador do sistema
NumberOfRvaAndSizes – Número e tamanho de RVA
DataDirectory – Diretório de dados constituído de uma matriz de 16 índices (com localização RVA e tamanho de cada peça de informação)

Seguindo temos a estrutura de cada índice do DataDirectory

struct _IMAGE_DATA_DIRECTORY {
    DWORD VirtualAddress;
    DWORD Size;
} IMAGE_DATA_DIRECTORY;

VirtualAddress – endereço da seção
Size – tamanho da seção

Começando do índice 0 temos as seguintes estruturas em DataDirectory:

enum E_DIRECTORY_ENTRY {
    IMAGE_DIRECTORY_ENTRY_EXPORT,
    IMAGE_DIRECTORY_ENTRY_IMPORT,
    IMAGE_DIRECTORY_ENTRY_RESOURCE,
    IMAGE_DIRECTORY_ENTRY_EXCEPTION,
    IMAGE_DIRECTORY_ENTRY_SECURITY,
    IMAGE_DIRECTORY_ENTRY_BASERELOC,
    IMAGE_DIRECTORY_ENTRY_DEBUG,
    IMAGE_DIRECTORY_ENTRY_COPYRIGHT, // IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
    IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
    IMAGE_DIRECTORY_ENTRY_TLS,
    IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
    IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
    IMAGE_DIRECTORY_ENTRY_IAT,
    IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
    IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTION,
}; 

Agora temos o bloco de código _IMAGE_SECTION_HEADER onde a quantidade é definida em _IMAGE_FILE_HEADER.NumberOfSections

typedef struct _IMAGE_SECTION_HEADER {
    BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // IMAGE_SIZEOF_SHORT_NAME 8
    union {
        DWORD PhysicalAddress;
        DWORD VirtualSize;
    } Misc;
    DWORD VirtualAddress;
    DWORD SizeOfRawData;
    DWORD PointerToRawData;
    DWORD PointerToRelocations;
    DWORD PointerToLinenumbers;
    WORD NumberOfRelocations;
    WORD NumberOfLinenumbers;
    DWORD Characteristics;
} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;

Name – Nome da seção tendo no máximo 8 caracteres
Misc.PhysicalAddress, Misc.VirtualSize – dividem o mesmo valor, sendo o endereço físico ou o tamanho virtual.
VirtualAddress – endereço virtual
SizeOfRawData – tamanho
PointerToRawData – ponteiro do inicio do arquivo até os dados da seção
PointerToRelocations – ponteiro para remanejamento para arquivos objetos
PointerToLinenumbers – ponteiro para o número de linhas para arquivos objetos
NumberOfRelocations – número de remanejamentos para arquivos objetos
NumberOfLinenumbers – quantidade de números de linhas para arquivos objetos;
Characteristics – características que descrevem como a memória da seção deve ser trata

Estrutura dos DataDirectory começando pelo IMAGE_DIRECTORY_ENTRY_EXPORT

struct _IMAGE_EXPORT_DIRECTORY {
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD Name;
    DWORD Base;
    DWORD NumberOfFunctions;
    DWORD NumberOfNames;
    DWORD AddressOfFunctions;
    DWORD AddressOfNames;
    DWORD AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;

Characteristics – Características de exportação. Atualmente não são usadas
TimeDateStamp – Data/hora em que as exportações foram criadas
MajorVersion – número de versão maior das exportações, não utilizado e setado como 0
MinorVersion – número de versão menor das exportações, não utilizado e setado como 0
Name – endereço relativo para o nome associado as exportações.
Base – valor ordinal inicial a ser utilizado para exportação do executável.
NumberOfFunctions – número de funções na tabela de exportação
NumberOfNames – número de nomes na tabela de exportação, esse valor vai ser sempre menor ou igual ao NumberOfFunctions
AddressOfFunctions – endereço relativo da tabela de exportação em uma matriz, cada índice diferente de 0 corresponde a um símbolo exportado.
AddressOfNames – endereço relativo da tabela de exportação nomes em uma matriz, cada índice corresponde a um símbolo exportado pelo nome.
AddressOfNameOrdinals - endereço relativo da tabela ordinal de exportação. Essa tabela é um conjunto de palavras.

Estrutura IMAGE_IMPORT_DESCRIPTOR

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    _ANONYMOUS_UNION union {
        DWORD Characteristics;
        PIMAGE_THUNK_DATA OriginalFirstThunk;
    } DUMMYUNIONNAME;
    DWORD TimeDateStamp;
    DWORD ForwarderChain;
    DWORD Name;
    PIMAGE_THUNK_DATA FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;

OriginalFirstThunk – esse campo é mal nomeado, ele contém um endereço relativo da tabela de nomes de importação. Isto é uma matriz de IMAGE_THUNK_DATA. Esse campo é 0 para indicar o final da matriz.
TimeDateStamp - recebe o valor 0 caso o executável não esteja vinculado a DLL importada. Quando tem a ligação é definido a data/hora quando a ligação ocorreu.
ForwarderChain – este é o índice da primeira API encaminhada. Definido como -1 se não tiver encaminhadores.
Name – endereço relativo para o nome da dll importada.
FirstThunk - endereço relativo a tabela de endereço de importação. É uma matriz de estruturas IMAGE_THUNK_DATA.

Estrutura IMAGE_THUNK_DATA

typedef struct _IMAGE_THUNK_DATA {
    union {
        LPBYTE ForwarderString;
        PDWORD Function;
        DWORD Ordinal;
        PIMAGE_IMPORT_BY_NAME AddressOfData;
    } u1;
} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;

u1.ForwarderString – endereço relativo para um texto transitário
u1.Function – endereço da função importada
u1.Ordinal – valor ordinal da função importada
u1.AddressOfData – endereço relativo para um IMAGE_IMPORT_BY_NAME com o nome da função importada

Estrutura IMAGE_IMPORT_BY_NAME

typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD Hint;
    BYTE Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

Hint – Dica para o carregador com o ordinal
Name – Nome da função importada

Estrutura IMAGE_RESOURCE_DIRECTORY

typedef struct _IMAGE_RESOURCE_DIRECTORY {
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    WORD NumberOfNamedEntries;
    WORD NumberOfIdEntries;
} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;

Characteristics – Não usado
TimeDateStamp – Não usado
MajorVersion – Não usado
MinorVersion – Não usado
NumberOfNamedEntries – Número de entradas com nome
NumberOfIdEntries – Número de entrada com id

Estrutura IMAGE_DEBUG_DIRECTORY

typedef struct _IMAGE_DEBUG_DIRECTORY {
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD Type;
    DWORD SizeOfData;
    DWORD AddressOfRawData;
    DWORD PointerToRawData;
} IMAGE_DEBUG_DIRECTORY,*PIMAGE_DEBUG_DIRECTORY;

Characteristics – Não usado e setado como 0
TimeDateStamp – Data/hora desta informação de depuração
MajorVersion - A versão maior desta informação de depuração. Não usado
MinorVersion – a versão mínima desta informação de depuração. Não usado.
Type - O tipo de informação de depuração. Os tipos são IMAGE_DEBUG_TYPE_COFF, IMAGE_DEBUG_TYPE_CODEVIEW, MAGE_DEBUG_TYPE_FPO, IMAGE_DEBUG_TYPE_MISC, IMAGE_DEBUG_TYPE_OMAP_TO_SRC, IMAGE_DEBUG_TYPE_OMAP_FROM_SRC, IMAGE_DEBUG_TYPE_BORLAND
SizeOfData - O tamanho dos dados de depuração neste arquivo. Não inclui o tamanho dos arquivos de depuração externo como .PDBs
AddressOfRawData – endereço relativo dos dados de depuração, quando mapeado na memória. Setado como 0 caso não seja mapeado.
PointerToRawData – Ponteiro para o dado de depuração. Não é endereço relativo.

Estrutura _IMAGE_TLS_DIRECTORY, IMAGE_TLS_DIRECTORY32

typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD StartAddressOfRawData;
    DWORD EndAddressOfRawData;
    DWORD AddressOfIndex;
    DWORD AddressOfCallBacks;
    DWORD SizeOfZeroFill;
    DWORD Characteristics;
} IMAGE_TLS_DIRECTORY32,*PIMAGE_TLS_DIRECTORY32;

StartAddressOfRawData – endereço inicial de um intervalo de memória usado para iniciar novos segmentos TLS na memória
EndAddressOfRawData – endereço final do intervalo na memória usada para inciar novos segmentos TLS na memória.
AddressOfIndex – endereço do índice que localiza o segmento de dados local. Quando um executável é trazido pra memória e uma seção .tls está presente, o carregador aloca um controlador TLS via TlsAlloc. Isto armazena o endereço fornecido nesse campo.
AddressOfCallBacks - endereço de uma matriz de ponteiros funções PIMAGE_TLS_CALLBACK. Quando um thread é criado ou destruído, cada função na lista é chamada. O final da lista é indicado por um ponteiro nulo. Em executáveis normais em visual c++ essa lista é vazia
SizeOfZeroFill - tamanho em bytes dos dados de inicialização, além dos dados iniciados serem delimitados pelos campos StartAddressOfRawData e EndAddressOfRawData. Todos os dados de threads iniciados depois desse intervalo é iniciado em 0.
Characteristics – Reservado, definido como 0

Estrutura IMAGE_DELAY_IMPORT_DESCRIPTOR

typedef struct _IMAGE_DELAY_IMPORT_DESCRIPTOR {
    DWORD grAttrs;
    DWORD szName;
    DWORD phmod;
    DWORD pIAT;
    DWORD pINT;
    DWORD pBoundIAT;
    DWORD pUnloadIAT;
    DWORD dwTimeStamp;
} IMAGE_DELAY_IMPORT_DESCRIPTOR, *LPIMAGE_DELAY_IMPORT_DESCRIPTOR;

grAttrs - Os atributos para essa estrutura. Atualmente, a única bandeira é definida dlattrRva (1) indicando que os campos de endereço na estrutura deve ser tratado como endereços relativos, em vez de endereços virtuais.
szName – endereço relativo com o nome da dll importada. esse valor é passado para o LoadLibrary
phmod – endereço relativo para uma localização na memória para um HMODULE. Quando a dll é trazida para a memória ela é armazenada a partir do HMODULE.
pIAT – endereço relativo para a tabela de endereços de importação para essa dll. Este é o mesmo formato de um IAT regular
pINT – endereço relativo para o nome da tabela de importação para essa dll. Este é o mesmo formato como um INT regular
pBoundIAT – endereço relativo do limite IAT opcional. um endereço relativo a uma cópia encadeada de uma tabela de endereços de importação para essa dll. Este é o mesmo formato de um IAT regular. Atualmente, está cópia do IAT não é realmente ligado, mas esse recurso pode ser adicionado em futuras versões do programa BIND.
pUnloadIAT – endereço relativo de uma cópia opcional o IAT original. Um endereço relativo para uma cópia não ligada de uma tabela de endereços de importação para essa DLL. Este é o mesmo formato de um IAT regular. Atualmente é definido como 0
dwTimeStamp – Data/hora que a dll foi importada. Normalmente definido como 0.

Referências
PE Format (PDF) 373kb
An In-Depth Look into the Win32 Portable Executable File Format Part 1 - http://msdn.microsoft.com/en-us/magazine/bb985996.aspx
An In-Depth Look into the Win32 Portable Executable File Format Part 2 - http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
http://msdn.microsoft.com/en-us/magazine/ms809762.aspx

domingo, 25 de agosto de 2013

Aplicativo android com horários de ônibus

Ha muito tempo tive em mente em desenvolver um aplicativo para android com os horários dos ônibus da minha cidade (Resende/RJ), finalmente coloquei o projeto em prática e ai está o resultado. Pretendo atualiza-lo com novos recursos e opções. Espero que gostem, avaliem e deêm sugestões/críticas/elogios pelo formulário do meu site.

Você pode baixar o aplicativo para o seu android clicando aqui.



Futuras atualizações serão postada aqui.

Att, Gilson Fabiano.

sexta-feira, 12 de julho de 2013

Carregando uma dll apartir da memória

Quando se trata de fazer hack's ou vírus o quanto mais stealth for seu código melhor, certo? Exato!

Ao desenvolver um hack para um jogo, vi a necessidade do código ser mais oculto possível. Nisso comecei a codificar e bolar algumas coisas e nisso pensei: porque não carregar meu código apartir da memória?.

Até ai tudo bem, fiz um código que carregava o código da dll na memória do jogo e executava o DllEntry. A primeira vista eu sorri alegremente até ver meu código dar um "access violation", fiquei triste (eu confesso). Depurando um pouco meu código vi que ele não resolvia as referências das funções e nem alocava de modo correto os setores da dll (nessa hora fiquei mais triste ainda).

Com todo o ocorrido resolvi apelar, fui no google e achei exatamente o que eu queria, um cara chamado Joachim Bauch desenvolveu um código (git) e um tutorial (link em inglês) explicando como fazê-lo (Foi tiro e queda).

Única coisa foi que tive que portar as minhas necessidades, já que se trata de uma dll injetável, essa dll injetável que carregava a outra dll, já que o código carrega a dll no processo atual (se é que vocês entenderam a embolação).

O código abaixo ilustra como é fácil carregar a dll apartir da dll injetada.

void InjectDll()
{
    FILE *fp;
    DWORD dwSize;
    unsigned char *data;
    HMEMORYMODULE handle;

    fp = fopen(DLLFILE, "rb"); // DLLFILE = minha dll

    fseek(fp, 0, SEEK_END);
    dwSize = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    data = (unsigned char*)malloc( dwSize );
    fread(data, dwSize, 1, fp);

    handle = MemoryLoadLibrary(data);
    if (handle == NULL)
    {
        // não foi possível carregar a dll
    }
    else
    {
        // dll carregada e DllEntry executado.
    }
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            InjectDll();
            return FALSE; // assim esse dll e descarregada automáticamente.
    }
    return TRUE;
}

Reparem no return FALSE; assim a dll é descarregada automáticamente, não deixando rastros :P. Do contrário a dll iria ficar lá.

Então meus pequenos, boa sorte nas suas brincadeiras e códigos.

Att, Gilson Fabiano

segunda-feira, 24 de junho de 2013

Engenharia reversa, o prazer em desmontar as coisas

Desde pequeno tenho o gosto de desmontar as coisas, eu não tive muitos brinquedos e os poucos que tinha eu desmontava todos. Meu pai devia pensar que eu destroçava os brinquedos, mas eu procurava ver o funcionamento das coisas por dentro e ainda continuo e claro meus brinquedos mudaram.

Quando ganhei meu primeiro computador passei os 3 primeiros meses sem ver a luz do dia literalmente – Era um Positivo com míseros 128mb de RAM mas que rodava o counter-strike – com a falta de instrução, resolvi procurar por mim mesmo com os recursos disponíveis.

Nesses 3 primeiros meses mexi no windows xp de cabo a rabo, como eu não tinha acesso à internet naquela época, lembro que achei o utilitário msconfig olhando arquivo por arquivo na pasta system32. Bons tempos aquele.

Enfim, voltando ao assunto de desmontar, ver como tudo funciona é prazeroso, olhar as coisas se encaixando e funcionando é uma sensação que não consigo explicar. Mas o mal de desmontar as coisas é montar novamente e deixar tudo funcionando como antes – já estraguei muito carrinho assim.

Com o computador não foi diferente, mas é claro que eu não ia violar a garantia abrindo o danado, parti logo para ver como tudo funcionava, abri muitas dlls, muitos exes no bloco de notas e só via coisa estranha, como eu não entendi nada daquilo eu só ficava boiando.


Aprendendo programação, fui entendendo aos poucos como era brilhante e complexo o funcionamento do computador, pelo menos pra mim, me fascinava. Hoje com o conhecimento que tenho vejo que falta muito a aprender.

Mas o que tem a ver desmontar carrinhos e desmontar softwares?

A ideologia é a mesma e o prazer também, mas sem perdas de peças como ocorre no hardware. Com o software quando não dá certo basta reiniciar.

Lembro do primeiro software que violei, era um que mostrava as senhas do antigo MSN, o software era pago e precisava de uma licença pra mostrar a senha por completo. Lembro que fiquei todo bobo com aquilo, e quem não ficaria?

Hoje em dia quebro alguns softwares que utilizo, como o conversor de dvd e um servidor dlna.

É errado? Pode ser que sim. Mas tudo que é errado é mais legal. ;)


Então se você é pai e leu isso, quando ver seu filho desmontando um carrinho, ajude-o e mostre como aquilo funciona, pois seu pequeno garoto pode virar um grande profissional em engenharia reversa. E o mercado paga muito bem para esses profissionais.

Para terem uma idéia existe um filme chamado "O Pagamento (Paycheck)", o ator principal é uma especialista em engenharia reversa onde ele cria uma máquina que prever o futuro.

Att, Gilson Fabiano

segunda-feira, 11 de março de 2013

Sublime Text 2/3 Build 2126-3019 + Patch

Sublime Text 3

Lançado apenas para membros registrados (até o momento), tras novos recursos e melhorias que podem ser conferidas no site oficial. O build atual é 3019 que pode ser baixado aqui (windows x86).

Sublime Text 2

O nosso querido Sublime Text 2 se graduou saindo do Beta. Seu Build atual é 2217 (versão 2.0.1).
Você pode baixar a nova versão do Sublime Text 2 por aqui.

Patch

O patch agora é multi versão desde o build 2126 até o atual 3019, mas apenas suportando versões do windows para arquitetura x86 (32 bits).
Acesse aqui e baixe o patch!

Em caso de dúvidas entre em contato por aqui.

Att, Gilson Fabiano

domingo, 3 de março de 2013

C++, Barra de progresso nos botões da barra de tarefas no Windows 7.

Deixar o character "afk" as vezes fica um tanto complicado, ainda mais quando PK'lowlevel ta sem nada pra fazer. Como o cliente não dá a opção de mostrar na barra de tarefa a vida do personagem, resolvi implementar.
No começo foi trabalhosso devido ao pacote do compilador não ter incluso os headers necessários e por eu não ter usado o CoInitialize() corretamente. Depois de muitas horas, tentativas e pesquisas descobri que não estava iniciando a biblioteca COM (por isso o EAX ficava com o cara de tacho). Mas graças ao todo poderoso oráculo (vulgo google) tudo se encaixou.

Vamos dá uma olhada num exemplo e ver como implementar esse estilo em uma janela do bloco de notas aberta.

#include <windows.h>
#include <shobjidl.h>

const GUID my_IID_ITaskbarList3 =
{ 0xea1afb91, 0x9e28, 0x4b86, { 0x90, 0xe9, 0x9e, 0x9f, 0x8a, 0x5e, 0xef, 0xaf } };

const GUID my_CLSID_TaskbarList =
{ 0x56fdf344, 0xfd6d, 0x11d0, { 0x95, 0x8a, 0x00, 0x60, 0x97, 0xc9, 0xa0, 0x90 } };

ITaskbarList3* ptbl = NULL;

int main()
{
    // inicia a biblioteca
    CoInitialize(NULL);
    // cria a instancia para a interface ITaskbarList3
    CoCreateInstance(my_CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, my_IID_ITaskbarList3, (LPVOID*)&ptbl);
    // procura por uma janela do bloco de notas
    HWND hWindow = FindWindow("Notepad", NULL);
    ptbl->SetProgressState(hWindow, TBPF_ERROR);
    ptbl->SetProgressValue(hWindow, 40, 100);
    return 0;
}


Recomendo o link onde o autor faz uma introdução de COM e explica o que é e como usar (texto em inglês).


Att, Gilson Fabiano.

quinta-feira, 14 de fevereiro de 2013

C++, Chamando endereços como se fossem funções

Quando se usa uma dll injetável ou algum outro código, saber o endereço da função não é o suficiente - as vezes. Para evitar de códigos em asm massivos em seu código fonte podemos criar um tipo da função ou simplesmente usar uma sintaxe.

Sintaxe


type-return ([modifier] *[variable])([type , [type , [type , ...]]])

Veja


void (*variavel)(int, int, char); // declara a variavel
variavel = (void(*)(int, int, char))0x00FF00FF; // atribui o valor do seu endereço a ser chamado
variavel(10, 20, 6);

ou

( (void(*)(int, int, char)) 0x00FF00FF ) (10, 20, 6);

Código de exemplo


void function1(int x, int y, char z)
{
    printf("Function1 - X: %d, Y: %d, Z: %d\n", x, y, z);
}
int function2(int x, int y, char z)
{
    printf("Function2 - X: %d, Y: %d, Z: %d\n", x, y, z);
    return (x + y + z);
}
int main()
{
    void(*f1)(int, int, char);
    int (*f2)(int, int, char);

    f1 = &function1;
    f2 = &function2;

    f1(1,2,3);
    int result = f2(4,5,6);

    printf("Result: %d", result);

    return 0;
}


Att, Gilson Fabiano

segunda-feira, 21 de janeiro de 2013

C++, Trabalhando com flags (bits)

Trabalhar com 32 bits é fácil num compilador x86, mas quando isso
variavel = 1 << 33;
torna-se inpertinente as coisas começam a ficar sérias. Em prol disso fiz algumas funções que sanam essa necessidade (não que o bitset não o faça) de trabalhar com mais de 32 bits (agora o flag é infinito filhote).

Segue as funções

void set_flag(char *flags, int flag)
{
    flags[ (int)((float)(flag +1) / 8.0) ] |= (1 << (flag % 8));
}
void remove_flag(char *flags, int flag)
{
    flags[ (int)((float)(flag +1) / 8.0) ] ^= (1 << (flag % 8));
}
bool has_flag(char *flags, int flag)
{
    return (int)flags[ (int)((float)(flag +1) / 8.0) ] & (1 << (flag % 8));
}

set_flag seta bit 1, remove_flag seta bit 0 e has_flag verifica se o bit é 1. O indice usado é 0. A função não verifica estouro de memória, portando cuidado!


Exemplo

char flags[1] = {0}; // 1 byte = 8 bits
set_flag((char*)flags, 1); // liga o segundo bit
set_flag((char*)flags, 2); // liga o terceiro bit
printf("%d\n", has_flag(flags, 0) )
printf("%d\n", has_flag(flags, 1) )

quarta-feira, 4 de julho de 2012

Variáveis anônimas no C++

Procurando por uma referência de uma app que baixei pro meu novo celular com android ;D~, na dropdown do google aparece "c++ anonymous objects", como nunca tinha visto isso resolvi ver quais seriam os resultados.
O primeiro resultado que aparece é do learncpp, esse: http://www.learncpp.com/cpp-tutorial/814-anonymous-variables-and-objects/, no texto o autor fala:

Quando a expressão nX + nY é avaliado, o resultado é colocado em uma variável anónima e sem nome. Uma cópia da variável anónima é retornado para o chamador por valor.

Então é criado uma variável anônima? Como sou muito curioso resolvi por a prova.

Compilei as seguintes funções usando o compilador GCC 4.6.1 sem nenhum parâmetro de aumento de performace:

int add(int x, int y)
{
    return x + y;
}
int add2(int x, int y)
{
    int tmp = x + y;
    return tmp;
}

Eis seus códigos em máquina:

// add(int x, int y)
PUSH EBP
MOV EBP,ESP
MOV EAX,DWORD PTR SS:[EBP+0C]
MOV EDX,DWORD PTR SS:[EBP+8]
ADD EAX,EDX
POP EBP
RETN

// add2(int x, int y)
PUSH EBP
MOV EBP,ESP
SUB ESP,10
MOV EAX,DWORD PTR SS:[EBP+0C]
MOV EDX,DWORD PTR SS:[EBP+8]
ADD EAX,EDX
MOV DWORD PTR SS:[EBP-4],EAX
MOV EAX,DWORD PTR SS:[EBP-4]
LEAVE
RETN

Agora cadê a variável criada no add(int x, int y)? Se olharmos bem no registrador EAX é posto o valor y, no EDX é posto o valor x e por final é adicionado EDX ao EAX, só isso!

No add2(int x, int y) acontece o mesmo, mas só que no final há uma referência a nossa variável int tmp, após os cálculos a variável tmp vai pra pilha MOV DWORD PTR SS:[EBP-4, EAX e logo em seguida é colocada no registrador de retorno EAX.

Analizando meus dados acima é de fato que não existem variáveis anônimas (não no meu compilador), não as que ele disse. Mas pode ocorrer de existir, não sei, vai saber!

Att, Gilson Fabiano

quarta-feira, 25 de abril de 2012

Injetando funções em aplicações

Veremos aqui uma técnica muito comum entre programadores de trainers/bots/macros que é a injeção de códigos em aplicações já compiladas sem alterar o estado fisíco do arquivo da aplicação. Caso queira pesquisar mais sobre o assunto procure por "inject dll", "hook function" e ainda "hooking function" tendo em base o "hook".

A aplicação que iremos modificar têm o seguinte código fonte:
#include <stdio.h>
#include <stdlib.h>

int T;

void get_number()
{
    printf("Enter Number: ");
    scanf("%d", &T);
}
int main()
{
    system("title my program");
    do
    {
        get_number();
    }
    while (T);
    return 0;
}

Nosso programa pede um número de entrada, caso esse número seja 0 ele sai, do contrário repete, e assim sucessivamente. Certo?
Continuando...
Iremos injetar um código que imprima na tela "You number entered are: <numero digitado>" toda vez que a get_number() for chamado. Para isso precisaremos saber os endereços da printf e a variável T na memória (O depurador usado aqui é o ollydbg).

Descobrindo os endereços

Para descobrirmos o endereço da função printf, vá em Search for > All intermodular calls,

Na janela "search" procure por printf e siga sua referência.

Iremos nos deparar com nossa função get_number(), apertando a tecla espaço iremos ver o endereço que se refere a printf, que no nosso caso é 0x00401A8C.

Agora falta só o endereço da variável T. Se olharmos direito veremos o endereço após a chamada da printf, onde começa as instruções da scanf, que é a referência da váriavel e o formato que iremos extrair. Então, BINGO! Temos também o endereço da variável T que no nosso caso é 0x00404008.

Procurando um local para injetar

Precisamos saber também onde iremos injetar nosso código para que fique similar a:
do
{
    get_number();
    printf("You number entered are: %d", T);
}
while (T);

Analizando as instruções

Encontramos um lugar perfeito para injetar nosso código, olhe bem no endereço 0x00401B4D a instrução MOV EAX, DWORD PTR DS:[program.404008] ela ocupa 5 bytes, a quantidade que precisamos.

Nota: Iremos sobrepor a instrução e adiciona-la em nosso código para não quebrar o fluxo original do programa.

Fazendo os códigos

Agora que temos os endereços e o local onde iremos injetar, só codificar!

Primeiro nosso código a ser injetado.
typedef void t_call(...);

#define _printf(...) ((t_call*)0x00401A8C)(__VA_ARGS__) // nossa printf

int get_number_hook()
{
    asm(".intel_syntax noprefix\n"); // muda a sintaxe pro intel
                                     // adicionar -masm=intel no build
    _printf((char*)0xFFFFFFFF, *((int*)0x00404008)) // nossa chamada, com a variavel T

    asm("mov eax, dword ptr ds:[0x404008]"); // instrução sobreposta pelo nosso jmp
    asm("mov edx, 0x00401B52");
    asm("jmp edx");
}
void get_number_hook_end(){}; // apenas para saber onde o get_number_hook termina

Nossas funções de injetar e alocar os dados na memória.
void hook(HANDLE hProc, DWORD address, DWORD funaddr) // injeta nosso código
{
    char JMP[5] = {0};
    JMP[0] = 0xE9;
    *(PDWORD)&JMP[1] = funaddr - address - 5;
    DWORD OldProtect;
    VirtualProtectEx(hProc, address, 5, PAGE_EXECUTE_WRITECOPY, &OldProtect);
    WriteProcessMemory(hProc, address, &JMP, 5, NULL);
    VirtualProtectEx(hProc, address, 5, OldProtect, NULL);
}
DWORD alloc(HANDLE hProcess, PVOID pointer, DWORD size) // aloca os dados
{
    LPVOID addr = VirtualAllocEx(hProcess, 0, size, MEM_COMMIT | MEM_RESERVE ,PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(hProcess, addr, pointer, size, NULL);
    return addr;
}

Dando uma atenção em *(PDWORD)&JMP[1] = funaddr - address - 5. Como o JMP é relativo a sua posição atual, é subtraido da posição de destimo a posição atual mais os 5 bytes da instrução. O resto do código é alto explicativo.

Faltando apenas nossa função principal, o main:
int main()
{
    DWORD pID;
    HWND hWnd = FindWindow(NULL, "my program");

    if (hWnd && GetWindowThreadProcessId(hWnd, &pID))
    {
        HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pID);
        if (hProc)
        {
            DWORD straddr, funaddr;

            printf("HWND: %d\n"  , hWnd );
            printf("PID: %d\n"   , pID  );
            printf("HANDLE: %d\n", hProc);

            printf("Injetando get_number_hook()");

            char *my_str = "You number entered are: %d\n";
            // aloca nosso texto e retorna o endereço 
            straddr = alloc(hProc, my_str, strlen(my_str));

            // aloca nosso código e retorna o endereço
            funaddr = alloc(hProc, &get_number_hook, (DWORD)((DWORD)&get_number_hook_end - (DWORD)&get_number_hook));

            // lembra do _printf((char*)0xFFFFFFFF...) ?
            // muda ao endereço do 0xFFFFFFFF para nosso texto
            WriteProcessMemory(hProc, funaddr + 0x0F, &straddr, 4, NULL);

            // injeta nosso código em 0x00401B4D
            hook(hProc, 0x00401B4D, funaddr);

            CloseHandle(hProc);
        }

    }

    return 0;
}

Dando a atenção devida em WriteProcessMemory(hProc, funaddr + 0x0F, &straddr, 4, NULL), onde mudaremos o endereço para nosso texto alocado anteriormente. Para entender o porque o do funaddr + 0x0F veja a imagem do nosso código compilado e alocado:

Olhe a quantidade de bytes que temos que pular até chegar no endereço que queremos mudar. 15 bytes sendo 0x0F o mesmo que 15 em hexadecimal. Sendo assim temos a posição da função alocada mais 15 bytes.

Downloads

Código fonte e executáveis (5kb)

Conclusão

Muitas coisas podem ser feita com essa técnica, o que mostrei aqui foi apenas o básico. Boa sorte em suas aplicações. ;)

Att, Gilson Fabiano

segunda-feira, 9 de abril de 2012

Tibia MC Patcher 9.51+

Tibia MC Patcher 9.51+

Software que ativa ou desativa o recurso de abrir mais de uma instância (multi cliente) do Tibia.


Download:

TibiaMC.7z (9kb)

Att, Gilson Fabiano

sexta-feira, 6 de abril de 2012

Criando Dialogs com C++ em ambientes Windows

Criar dialogs (janelas) em ambientes Windows é algo fácil e muitos programadores não se interessam pelo C++ por não ter essa facilidade como no Delphi e Visual Studio, por exemplo.
Mal sabem eles que é muito mais fácil do que imaginam.

Existem várias formas fáceis para criação de dialogs, tanto em matéria de performace, quanto em tamanho em bytes.
Usaremos aqui um editor de recursos (ResEdit) e um IDE (Code::Blocks) usando um compilador GCC 4.6.1, com um conjunto de funções da API do Windows: CreateDialog, DialogBox, EndDialog, PostQuitMessage, IsDialogMessage, GetMessage, TranslateMessage, DispatchMessage, DialogProc, entre outras.

Caso ainda não tenha um ambiente de desenvolvimento leia esse artigo escrito pelo meu amigo Thiago Suchorski, nele é ensinado passo a passo como faze-lo.

Nosso projeto terá 4 arquivos (mais abaixo está para download o projeto todo):
  • main.cpp -- arquivo com nossas funções.
  • resource.h -- cabeçalho do recusro, onde são definidos os IDs.
  • resource.rc -- arquivo com os recursos.
  • manifest.xml -- arquivo de manifest, responsável pelo uso dos temas na dialog

No main.cpp segue o código:

#include <windows.h>
#include "resource.h"

HINSTANCE hInstance;

/* função de eventos da janela sobre */
BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_CLOSE:
            EndDialog(hwnd, 0);
            return TRUE;

        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case ID_ABOUT_OK:
                    EndDialog(hwnd, 0);
                    return TRUE;
            }
    }
    return FALSE;

}
/* função de eventos da janela principal    */
BOOL CALLBACK WindowProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_CLOSE:
            PostQuitMessage(0);
            return TRUE;

        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case ID_OK:
                case IDM_SAIR1:
                    PostQuitMessage(0);
                    return TRUE;

                case IDM_SOBRE1:
                    DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG2), hwnd, (DLGPROC)DialogProc);
                    return TRUE;

                default:
                    return TRUE;
            }
    }

    return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInstance = hInst;
    HWND hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, WindowProcedure);
    if (!hWnd) return 1;
    MSG Msg;
    while(GetMessage(&Msg, NULL, 0, 0) && hWnd)
    {
       if(!IsDialogMessage(hWnd, &Msg))
       {
           TranslateMessage(&Msg);
           DispatchMessage(&Msg);
       }
    }
    return Msg.wParam;
}

Vamos destacar as funções CreateDialog e DialogBox com suas respectivas funções de tratamento de eventos. Mas porque usar EndDialog ao invés de PostQuitMessage na DialogProc da DialogBox? Porquê a PostQuitMessage indica que o aplicativo está sendo finalizado e não que a janela está sendo fechada, por isso o uso da EndDialog. Mas o uso da PostQuitMessage nas funções de tratamento da DialogBox é válido.

Arquivo resource.h

#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif

#define IDD_DIALOG1                             100
#define IDR_MENU1                               101
#define IDD_DIALOG2                             102
#define ID_OK                                   1000
#define ID_ABOUT_OK                             1001
#define IDM_SOBRE1                              40000
#define IDM_SAIR1                               40001

E o resource.rc

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
//
// Menu resources
//
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE
IDR_MENU1 MENU
{
    POPUP "Arquivo"
    {
        MENUITEM "Sair", IDM_SAIR1
    }
    POPUP "Ajuda"
    {
        MENUITEM "Sobre", IDM_SOBRE1
    }
}
//
// Dialog resources
//
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE
IDD_DIALOG1 DIALOG 0, 0, 186, 76
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Tela de exemplo"
MENU IDR_MENU1
FONT 8, "Ms Shell Dlg"
{
    DEFPUSHBUTTON   "Fechar", ID_OK, 69, 58, 50, 14
    GROUPBOX        "Informação", IDC_STATIC, 4, 4, 178, 48
    CTEXT           "Um simples exemplo de como criar telas com c++ facilmente sem o uso do visual studio =)", IDC_STATIC, 11, 21, 166, 23, SS_CENTER
}
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE
IDD_DIALOG2 DIALOG 0, 0, 143, 68
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Sobre"
FONT 8, "Ms Shell Dlg"
{
    DEFPUSHBUTTON   "OK", ID_ABOUT_OK, 46, 50, 50, 14
    CTEXT           "Sobre o autor\n\nNome: Gilson Fabiano\nEmail: theafien@gmail.com", IDC_STATIC, 4, 4, 135, 35, SS_CENTER
}
//
// Manifest resources
//
LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE
1                  RT_MANIFEST    ".\\manifest.xml"

E por fim o manifest.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

Se você for um bom programador e seguir toda a lógica e fluxo dos códigos irá entender o funcionamento, do contrário releia até entender.

Downloads


Erros de português revisado pelo André Luiz.

Att, Gilson Fabiano.

quarta-feira, 21 de março de 2012

Python e GIFs animados

Trabalhando em um projeto precisei criar arquivos de imagens. Tudo ocorria bem até eu me deparar com um problema: Como criar uma imagem animada transparente?

O PIL não cria GIF's animados, apenas os lê.

Achei então um image2gif escrito por Almar Klein mas o script dele não cria GIF's com transparência.

Procurei formas alternativas usando o PIL como base e não achei nada, mas achei um código escrito em PHP por László Zsidi muito bom que faz exatamente o que estava procurando. Transcrevi o código pra Python e o resultado encontrasse abaixo para uso.

A classe trabalha com arquivos GIF da versão 87a e 89a. A dimensão final da imagem é baseada no primeiro frame.

GIF(frames, loops=0, dis=2, transparency=None)

frames
uma tupla com os frames onde o primeiro indice é o arquivo e o segundo indíce é o tempo do frame, o arquivo pode ser um open(..., 'rb'),  caminho do arquivo relativo ou absoluto, ou uma string contendo o a imagem.
 
loops
Quantidade de repetições da animação, onde 0 é repetição contínua.
 
dis
Disposição de cada frame. Onde 0, 1 uma imagem é jogada em cima da outra respeitando a transparência. E 2, 3 o efeito cascata não é aplicado.
 
transparency
Cor que será considera a cor alpha da imagem, dando o efeito de transparência.

GIF.create_animation()

Retorna um buffer contendo a imagem GIF animada.

Exemplo

from GIF import GIF
frames = [
    (open('410.gif', 'rb').read(), 40),
    (open('411.gif', 'rb'), 40),
    ('412.gif', 40),
    (open('413.gif', 'rb'), 40),
    (open('414.gif', 'rb'), 40),
    (open('415.gif', 'rb'), 40),
    (open('416.gif', 'rb'), 40),
    (open('417.gif', 'rb'), 40),
]
gif = GIF(frames, 2, 3, (255, 0, 255))
image = gif.create_animation() # retorna o buffer da imagem
open('animation.gif', 'w+b').write(image)    

Download

GIF.7z (Python, 5kb)
  • GIF.py -- módulo
  • 410.gif ~ 417.gif -- imagens de exemplo
  • animationjoin.gif -- imagem de resultado final
GIFEncoder.zip (PHP, 41kb) escrito por László Zsidi

Att, Gilson Fabiano

segunda-feira, 5 de março de 2012

Sublime Text 2 Beta, Build 2181 + Patch

O editor de texto que estou usando desde o ano passado chamasse Sublime Text 2. Antes eu usava uma forma alternativa do textmate para windows o e-texteditor -- além de ser um software pago, sua ultima atualização foi em 2010 --
Um dos recursos do textmate que me chamou atenção é que quando selecionado o texto tabulações, espaços, quebras de linhas e outros caracteres não imprimivéis são expostos (assim sei como meu texto está realmente).

Não é só por esse recurso que mudei pro Sublime Text 2, ele vem me conquistando cada vez mais que o utilizo. Eu particulamente recomendo esse editor até por ele ser multi plataforma.

Sublime Text 2 Beta agora está em seu Build 2181. Visite o site oficial para maiores informações.

Você pode baixar o Build 2181 por esse link e por esse o patch.

Quem fez o patch e o que ele faz?

O patch foi uma alternativa que eu criei para desativar as notificações que ocorre quando salva o arquivo em determinadas quantidades, além da notificação o patch também remove o UNREGISTERED da barra de titulo. Entretanto o patch funciona apenas em versões compiladas para windows 32 bits.

Use o patch por conta própria e risco.

Não me senti violando nenhuma licença ou similar, até porque não achei nenhuma licença vinculada ao software.

Att, Gilson Fabiano.

BBot 5.4 Retail

Disponibilizo ao publico a versão do BBot 5.4 crackeada.

Para saber mais verifique o site official do bot.

Como usar

Antes de abrir o BMega.exe execute o BMegas.exe (que simula o servidor de autentificação do BBot).
Feito isso, execute o BMega.exe normalmente e clique em Login.

Download 1.7 MB (SHA1 Checksum: a846a9314a6bc6d385893c36646a7e597b13bf39)

quinta-feira, 14 de abril de 2011

BBot 2.24 com Bypass

Pra quem conhece o BBot sabe que até a versão 1.92 ele era de graça, mas como todo mundo procura ganhar algo em cima dos seus serviços, o pessoal do BBot não foi diferente. Não é justo pagar por algo que deveria ser de graça. Bem sem mais delongas, você pode optar por baixar o BBot já com o bypass ou somente o bypass.

Descrição dos arquivos

bbotserver2.24_471kb: Bypass
Path.bat: Edita o arquivo hosts
PathAndRun.bat: Edita o arquivo hosts e executa o bbotserver2.24_471kb

Editando o arquivo hosts manualmente

Para usar o bbot 2.24 bypass é necessário editar um arquivo chamado hosts, esse fica em

%windir%\system32\drivers\etc\hosts

Abra o bloco de notas e abra o arquivo hosts

Após isso adicione 127.0.0.1 premium.bmega.net para que o arquivo hosts fique semelhante a imagem abaixo.

Pronto!

Agora sempre antes de iniciar o bot abra o bbotserver2.24_471kb.exe.

sexta-feira, 11 de fevereiro de 2011

Google Appengine e importando Django 1.2

Como no visto no texto anterior de como importar o django 1.1 ou similiar sem o uso zipimport, veremos aqui como importar o django 1.2.5 (final) ou similar sem o uso de zipimport e com mais praticidade.

Eu desconhecia da def use_library em google.appengine.dist que seria uma mão e bem mais prático se usado no texto anterior.

O Django 1.2 trás grandes melhorias, principalmente nas templatetags de condições como o IF, dando possibilidade de usar ==, !=, <, >, <=, >= e in, haha (eta-coisa-boa)!

No dev disponibilizado para os desenvolvedores não faz referência ao 1.2, portando é preciso editar na mão enquanto o pessoal do GAE não atualiza. Como visto no próprio arquivo _library.py. No final do texto é mostrado como editar o arquivo necessário para rodar localmente.

Bem, agora já temos conhecimento da use_library e a disponibilidade da versão 1.2 e o que nos resta fazer? IMPORTAR!

Segue o procedimento abaixo (saiba mais direto no appengine):

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

from google.appengine.dist import use_library
use_library('django', '1.2')

Nota: Lembre-se que o código acima deve ser inserido antes de qualquer chamada que envolva o django.

É necessário editar o arquivo _library.py localizado em %LOCAL-ONDE-O-APPENGINE-FOI-INSTALADO%google\appengine\dist  apartir da linha 80. Ela está mais ou menos assim:
PACKAGES = {
    'django': (DjangoVersion,
               {'0.96': None,
                '1.0': None,
                '1.1': None,
                }),

Adicione a versão "1.2" para que fique assim:

PACKAGES = {
    'django': (DjangoVersion,
               {'0.96': None,
                '1.0': None,
                '1.1': None,
                '1.2': None,
                }),

Salve o arquivo e pronto!

Nota: Lembre de ter o django 1.2 instalado.

Att, Gilson Fabiano.

terça-feira, 16 de novembro de 2010

Sempre ...

...
minhas palavras são simples
e assim sempre vai ser
não importa o que você diga
elas sempre serão pra você
querendo ou não, eu sou um sofredor
que por ser puro, ainda acredita no amor
...

Mais um fim de noite ...

...
Mais uma noite vai começando, junto dela meu sofrimento.
Eu vou preparar minhas armas pois já sei qual será meu tormento.

O pensamento é um vilão sem face que ataca direto no coração
Sem mais nem menos somos apanhados e jogados ao chão

Triste somos nós, possuidores de um coração escravizado
Que sofre todos os dias por ter o amor definhado

Creiamos poder um dia poder escapar
No estilo "O Conde de Monte Cristo"
Pro meu amor não mais se definhar.
...

terça-feira, 2 de novembro de 2010

Como restaurar a Lixeira no Windows XP?

Se você ou algum fiodeumaégua deletou a lixeira da área de trabalho no sistema operacional Windows XP e nem tem ídeia de como restaura-lá eis a solução:

Caso goste de comodidade baixe o arquivo de registro (caso a lixeira não volte vá pra seção Pedra no caminho) e pare por aqui mesmo, mas se gosta de por a mão na massa, gogo. =)

Mechendo no registro

  1. Vá no menu Iniciar e em seguida Executar (Win+R)
  2. Digite regedit e dê OK
  3. Vá para: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace
  4. Crie uma nova chave com o seguinte valor {645FF040-5081-101B-9F08-00AA002F954E}
  5. Dentro desta chave mude o valor (Padrão) para Lixeira
  6. Pronto!

Pedra no caminho

Caso tenha executado o arquivo de registro ou feito o passo-a-passo acima e a lixeira ainda não voltou, tente fazer o seguinte:

  1. Vá no menu Iniciar e em seguida Executar (WIN+R)
  2. Digite gpedit.msc
  3. A janela de Diretivas de grupo será aberta
  4. Vá em Configuração do usuário > Modelos administrativos > Área de trabalho (ou Desktop)
  5. Encontre o Item de configuração Remover o ícone 'Lixeira' da área de trabalho, e mude seu valor para Não-configurado caso não seja. (Veja a imagem)
Pronto a diretiva foi alterada, agora atualize a área de trabalho (F5), caso ainda ela não apareça relate seu problema nos comentários.

Fonte: http://www.forumpcs.com.br/comunidade/viewtopic.php?t=243435

Att, Gilson Fabiano