Hi,
Anteriormente, postei, nas linguagens C, C++ e Visual Basic, códigos relacionados a uma técnica que nos permite inserir dados dentro do código executável de um aplicativo, e fazer com este este, ao ser carregado, leia estes dados e realize diferentes tarefas. Nos exemplos, mostrei uma forma simples de armazenar um nome dentro do arquivo e fazer com este seja mostrado após a execução desse arquivo.
Para não aparentar preconceito com o Delphi, desta vez, irei mostrar a versão do código utilizando esta linguagem.
Irei fazê-lo de uma forma diferente, ao invés de ir desenvolvendo trecho por trecho, postarei o código completo e, posteriormente, cada trecho será explicado ;)
Go?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
nome: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
fp: TFileStream;
arq: string;
marca: array[0..3] of char;
buffer: PChar;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
CopyFile(PChar(arq),'TESTE.EXE',FALSE);
fp := TFileStream.Create('TESTE.EXE',fmOpenWrite);
fp.Seek(0,soFromEnd);
marca[0] := '*';
marca[1] := '*';
marca[2] := '*';
marca[3] := #0;
GetMem(buffer,length(nome.Text));
StrCopy(buffer,PChar(nome.text));
fp.WriteBuffer(marca,3);
fp.WriteBuffer(buffer^,length(nome.text));
FreeMem(buffer);
fp.free;
MessageBox(Handle,'EXE GERADO ^^','LOL',$40);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
pos: integer;
msg: PChar;
begin
arq := Application.ExeName;
fp := TFileStream.Create(arq,fmShareDenyNone);
GetMem(buffer,fp.size);
fp.Read(buffer^,fp.size);
pos := 0;
for i:= 0 to fp.size -1 do
if (buffer[i] = '*') and (buffer[i+1] = '*') and (buffer[i+2] = '*') then pos :=i;
if(pos > 0) then
begin
msg := buffer+pos+3;
MessageBox(0,msg,'Seu nome é: ',$40);
FreeMem(buffer);
fp.free;
ExitProcess(0);
end;
FreeMem(buffer);
fp.free;
end;
end.
Antes de prosseguirmos, perceba que temos dois controles adicionados ao formulário: um TextBox, cujo nome é nome (lol) e um botão denominado Button1.
Trecho por trecho:
var
Form1: TForm1;
fp: TFileStream;
arq: string;
marca: array[0..3] of char;
buffer: PChar;
Na parte inicial do código, temos a declaração de variáveis globais, isto é, variáveis que podem ser utilizadas a partir de qualquer função ou procedure dentro do código. A variável FORM1 é associada ao Form - porém isto não nos interessa ;).
A variável
fp é do tipo TFileStream - responsável por manipulamento de arquivos - e servirá de ponteiro para o próprio arquivo executável. Iremos armazenar o caminho e nome do executáve na variável
arq.
Para podermos saber onde começam os dados que foram escritos no arquivo, precisamos ter uma marca, esta será armazenada no array de chars
marca.
Por fim, temos o ponteiro para CHAR
buffer, que, além de servir para armazenar o conteúdo do executável, servirá também para inserir o nome digitado em seu código, se necessário (caso não exista).
Vamos analisar o trecho referente à inicialização do programa:
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
pos: integer;
msg: PChar;
begin
arq := Application.ExeName;
fp := TFileStream.Create(arq,fmShareDenyNone);
GetMem(buffer,fp.size);
fp.Read(buffer^,fp.size);
pos := 0;
for i:= 0 to fp.size -1 do
if (buffer[i] = '*') and (buffer[i+1] = '*') and (buffer[i+2] = '*') then pos :=i;
if(pos > 0) then
begin
msg := buffer+pos+3;
MessageBox(0,msg,'Seu nome é: ',$40);
FreeMem(buffer);
fp.free;
ExitProcess(0);
end;
FreeMem(buffer);
fp.free;
end;
As variáveis
i,
pos e
msg, servirão, respectivamente, para nos auxiliar em loop onde tentaremos encontrar a marca definida no código do executável, armazenar a posição desta marca, caso exista, e por fim, armazenar o nome digitado obtido dentro do arquivo. Veremos isso com mais calma.
O caminho do executável é armazenado na variável global
arq através da seguinte linha:
arq := Application.ExeName;
Note que, como a variável
arq é global, após essa atribuição, podemos utilizar o seu valor em qualquer função ou procedure.
Após obtermos o caminho do executável, este é aberto:
fp := TFileStream.Create(arq,fmShareDenyNone);
O parâmetro
fmShareDenyNone é utilizado para permitir que outros processos tenham acesso compartilhado sem restrições ao arquivo do executável. É necessário pois, na sua omissão, teríamos problemas ao abrir o arquivo, uma vez em que este já foi carregado - lembre-se que o programa está abrindo o seu próprio executável ;).
A variável
buffer será utilizada para armazenar o conteúdo do arquivo. Para que isso possa ser feito, o buffer deve conter um espaço suficiente para armazenar este conteúdo, por isso, utilizamos alocação dinâmica:
GetMem(buffer,fp.size); // Aloca no buffer o espaço de memória referente ao tamanho do arquivo - retornado pelo método fp.size
Lê-se o conteúdo do arquivo e o armazena no buffer:
fp.Read(buffer^,fp.size);
Note que utilizamos "buffer^" pois
buffer é um ponteiro.
Atenção especial:
for i:= 0 to fp.size -1 do
if (buffer[i] = '*') and (buffer[i+1] = '*') and (buffer[i+2] = '*') then pos :=i;
Agora que a variável "buffer" já contém o código do executável, iremos procurar pela marca
*** dentro deste. Se esta marca for encontrada, é sinal que existe um nome digitado.
A variável
i percorre todos os índices do buffer procurando pela seqüência de caracteres "***". Caso encontre-a, atribui-se à variável
pos a posição onde se detecta a primeira ocorrência.
Veja que o valor inicial de
pos é ZERO:
pos := 0;
Note ainda que, o valor de
pos só alterado caso a marca seja encontrada. Então, por lógica, se esta não for encontrada, o valor de
pos continua inalterado, ou seja, mantém-se igual ZERO. A partir dai, podemos verificar se existe ou não um nome armazenado no executável:
if(pos > 0) then
begin
msg := buffer+pos+3;
MessageBox(0,msg,'Seu nome é: ',$40);
FreeMem(buffer);
fp.free;
ExitProcess(0);
end;
FreeMem(buffer);
fp.free;
end;
É importante observar que, como iremos escrever o nome digitado no final do arquivo, não há como a marca
*** ficar situada no byte 0 do código, até porque, isso invalidaria o programa ;)
A função
length(nome.text) nos retorna o número de bytes que o nome digitado possui, como copiamos este último para o buffer, logo, o número de bytes que o buffer armazena é igual.
Liberam-se a memória alocado no buffer e o ponteiro para o arquivo:
FreeMem(buffer);
fp.free;
Frescura:
MessageBox(Handle,'EXE GERADO ^^','LOL',$40);
Abaixo segue o source utilizado no artigo (DELPHI 7):
Arquivo em Anexo - Security Ðarkers - wWw.darkers.com.br (http://www.darkers.com.br)FIM!
Bye
EB A MANO!!!!! vlWWWWW esse EXE ae é aquele que tu fez pra mim de ex? tipo tem uma outra forma bem fácil tbm, que pega uma 'base' (ark já pronto) e modifica e cria um novo. Eu testei aqui com meu trojan de reversa e ficou mto bom. Cara vlw seus posts são ótimos, vc ta sempre aki ajudando mt gente... isso é um incentivo aos iniciantes...
realmente, muito bom, agora tenho uma duvida, tem como eu criar componentes neste EXE GERADO ?
ja fiz varias coisas com elem o source ta exelente, mas tem como isso?
se puder me add no msn: www.operacaoremota.com.br (http://www.operacaoremota.com.br)
Obrigado e fico esperando uma resposta
da pra fazer isso com resources, a única coisa que tem de diferente, é que aki vc ta inserindo dados em si mesmo, com resources a gente extrai o soft do arquivo .res e dps editamos usando WriteFile

Show de bola, eu fiz um edit server com isso Dark Side, vlw ^^