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