Ir para conteúdo
Faça parte da equipe! (2024) ×
Conheça nossa Beta Zone! Novas áreas a caminho! ×
  • Quem está por aqui   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.

[TUTORIAL] Codigo de Injecção


MRs.Romanha
 Compartilhar

Posts Recomendados

1) O que é Código de Injeção??

 

Code injection é o ato de introduzir rotinas a um processo remoto, de modo a mudar o sua funcionabilidade. No caso, nós simplesmente iremos introduzir uma rotina e fazer o processo remoto executá-la, sem interferir em sua funcionabilidade.

 

 

2) Entendendo a lógica

 

Bom, para os que não estão muito familiarizados com manipulação de memória eu sugiro que estudem um pouco mais antes de tentar entender completamente o conceito de Code Injection. Bom, como estaremos mexendo com a memória de outro processo, quando formos usar algum parametro que está em NOSSO programa, não podemos simplesmente tentar chamá-lo de um processo para outro. Então nós escreveremos na memória do target (tratarei o processo remoto como "target" por questão de conveniência ao escrever) tudo que ele for usar que está em nosso processo.

 

A rotina que injetaremos no target deve estar numa DLL e sendo exportada.

 

Outro fator importante são os privilégios necessários para o nosso programa executar essa ação. Se tentarmos fazer isso com privilégios normais, é provável que, em algum momento do código, haja problemas de permissão. Para evitar quaisquer eventuais problemas, definiremos o privilégio como o de debug.

 

Depois de executada a rotina, não temos mais porque deixar os parametros utilizados na execução da mesma no target, isso só iria ocupar espaço, então nós liberaremos toda a memória escrita no processo remoto.

 

 

3) O código

 

Bom, antes de mais nada, vamos criar a estrutura que armazenará os parametros utilizados na execução da rotina. Mas que parametros são esses afinal??

 

Esses parametros devem incluir as funções LoadLibraryA (para carregar a DLL na memória) e GetProcAddress (para saber o endereço de memória da nossa rotina quando for injetada no target). Além dessas funções, também devemos por nessa estrutura os parametros de cada uma: o nome da DLL e o nome da rotina. Tendo isso em mente, definam a estrutura do seguinte modo:

 

 

type

TInjectParams = record

LoadLibrary: function (lpLibFileName: PAnsiChar): Cardinal; stdcall;

LibName: PAnsiChar;

GetProcAddress: function (hModule: Cardinal; lpProcName: PAnsiChar): Pointer; stdcall;

ProcName: PAnsiChar;

end;

PInjectParams = ^TInjectParams;

Agora, como na função final do Code Injection o usuário irá apenas especificar o nome do processo, da dll e da rotina a ser injetada, precisaremos de uma função que pega o Handle do processo a partir do nome dele. Para isso adicionem "tlhelp32" no uses e utilizem o seguinte método:

 

function GetProcess(proc: string): Cardinal;

var

Snap: THandle;

pe: TProcessEntry32;

begin

Snap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

if Snap = 0 then Exit;

if Process32First(Snap,pe) then

begin

repeat

if proc = pe.szExeFile then

begin

Result:=pe.th32ProcessID;

break;

end;

until not Process32Next(Snap,pe)

end

end;

Como dito acima, será necessário escrever na memória do target os parametros e a rotina em si. Para isso vamos criar duas funções, uma para escrever os parametros (WriteString) e uma para escrever a rotina (WriteData). Notem que elas são funções e não procedimentos pois precisamos do endereço de memória onde esses dados foram escritos para chamá-los a partir do target.

 

 

 

function WriteString(Process: Cardinal; s: string): Pointer;

var

bytes: Cardinal;

begin

Result:=VirtualAllocEx(Process, nil, length(s) + 1, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);

WriteProcessMemory(Process, Result , pchar(s), length(s) + 1, bytes);

end;

function WriteData(Process, dwSize: Cardinal; RemoteData: pointer): pointer;

var

bytes: Cardinal;

begin

Result:=VirtualAllocEx(Process, nil, dwSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);

WriteProcessMemory(Process, Result, RemoteData, dwSize, bytes);

end;

Agora precisaremos de uma rotina para executar a rotina injetada no target. Vamos chamá-la de RemoteFunction. Essa rotina precisará dos parametros injetados no target para executar a rotina desejada e, como os parametros já estarão definidos na memória, utilizaremos PInjectParams para pegar os valores.

 

 

procedure RemoteFunction(Parametros: PInjectParams); stdcall;

var

proc: procedure; stdcall;

begin

proc:=Parametros^.GetProcAddress(Parametros^.LoadLibrary(Parametros^.LibName),Pa

rametros^.ProcName);

proc;

end;

Agora precisaremos de um método para saber o tamanho dessa rotina descrita acima, pois na hora de escrevê-la no target é necessário por o tamanho. Para isso faremos outro método logo abaixo desse, e depois é só pegar o endereço dele e subtrair do endereço da rotina "RemoteFunction".

 

procedure RemoteFunctionend; stdcall;

begin;

end;

Como já disse anteriormente, é necessário mudar o privilégio para evitar eventuais problemas. Utilizem o seguinte método:

 

 

 

procedure ChangePrivilege(szPrivilege: PChar; fEnable: Boolean);

var

NewState: TTokenPrivileges;

luid: TLargeInteger;

hToken: THandle;

ReturnLength: DWord;

begin

OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken);

LookupPrivilegeValue(nil, szPrivilege, luid);

NewState.PrivilegeCount := 1;

NewState.Privileges[0].Luid := luid;

if (fEnable) then

NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED

else

NewState.Privileges[0].Attributes := 0;

AdjustTokenPrivileges(hToken, False, NewState, SizeOf(NewState), nil, ReturnLength);

CloseHandle(hToken);

end;

Pronto, agora só falta montar a função final, mas depois de tudo isso, para quem realmente entendeu a lógica fica fácil. Não vou comentar parte por parte dela no post, pois o código já está comentado.

 

 

 

procedure Inject(process, dll, code: string);

var

PID, hProcess, ThreadId, ThreadHandle: Cardinal;

RemoteData,RemoteFunc,LibFileName,ProcName: pointer;

Parametros: TInjectParams;

begin

{Pega o Handle do processo}

PID:=GetProcess(Process);

 

{Seta o privilégio de debug}

ChangePrivilege('SeDebugPrivilege', True);

 

{Abre o processo}

hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, PID);

 

{Define os parâmetros que serão usados para executar a procedure}

LibFileName:=WriteString(hProcess, dll);

ProcName:=WriteString(hProcess, code);

Parametros.LoadLibrary:=GetProcAddress(GetModuleHandle('kernel32'), 'LoadLibraryA');

Parametros.LibName:=LibFileName;

Parametros.GetProcAddress:=GetProcAddress(GetModuleHandle('kernel32'), 'GetProcAddress');

Parametros.ProcName:=ProcName;

 

{Abre um novo espaço de memória para guardar os parâmetros}

RemoteData:=WriteData(hProcess, sizeof(Parametros), @Parametros);

 

{Abre um novo espaço de memória para guardar a procedure}

RemoteFunc:=WriteData(hProcess, integer(@RemoteFunctionend) - integer(@RemoteFunction), @RemoteFunction);

 

{Cria a thread que executará a procedure}

ThreadHandle:=CreateRemoteThread(hProcess, nil, 0, RemoteFunc, RemoteData, 0, ThreadId);

WaitForSingleObject(ThreadHandle, 3000);

 

{Libera as memórias criadas}

VirtualFreeEx(hProcess,LibFileName,0,MEM_RELEASE);

VirtualFreeEx(hProcess,ProcName,0,MEM_RELEASE);

VirtualFreeEx(hProcess,RemoteFunc,0,MEM_RELEASE);

VirtualFreeEx(hProcess,RemoteData,0,MEM_RELEASE);

end;

4) Pondo tudo em prática

 

Criem uma DLL e adicionem uma rótina simples, como:

 

 

 

procedure Msg;

begin

MessageBox(0,'Teste','Code Injected',mb_ok);

end;

**Não esqueçam de declarar "windows" no uses

 

Depois exportem essa função. Digitem o seguinte abaixo de todas as eventuais rotinas que sua DLL tem:

 

exports

Msg;

Compilem essa DLL com o nome 'invaders.DLL'. Depois criem um projeto novo e coloquem um botão, além de todo o procedimento descrito acima. No onclick desse botão coloquem:

 

 

 

Inject('notepad.exe','C:\Projects\MRs.Romanha.DLL','Msg');

**Não se esqueçam de ao invés de "C:\Projects\MRs.Romanha.DLL", colocar o path da sua dll e de abrir o notepad antes de clicar no botão

 

Espero ter sido claro na explicação... Não me aprofundei muito na parte teórica pois teria que falar de assembly e ia acabar ficando ruim pra mim, vendo que eu não sou expert nessa linguagem, deixo este trabalho para quem tem mais experiência e estiver disposto!!

Link para o comentário
Compartilhar em outros sites

Este tópico está impedido de receber novos posts.
 Compartilhar

×
×
  • Criar Novo...

Informação Importante

Nós fazemos uso de cookies no seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies , caso contrário, vamos supor que você está bem para continuar.