ProSocks Library
I finally got frustrated enough waiting on the Simba developers to get Simba's sockets together.. So.. I wrote a plugin that should have some neat functionality and is 100% portable. It is statically compiled so no extra downloads required. I know Simba is open source and I can add the code to it myself.. Just thought a plugin would handle it better and it would be easy for anyone to use it without having to re-install or re-download Simba.
Features:
SSL & TLS enabled.
Read/Write/Accepts, GET, POST, etc.
Email (SMTP), POP3, etc.
Future Features (maybe):
Lape style structures.
Download:
https://github.com/Brandon-T/ProSocks/releases
If using ASM (ProSocks v.01):
ASM Code:
format PE console
entry main
include 'Code/FASM/include/macro/import32.inc' ;Includes
section '.idata' import data readable
;Imports
library msvcrt,'msvcrt.dll', prosocks,'prosocks.dll'
import msvcrt, printf, 'printf',\
exit,'exit', getchar, 'getchar', scanf, 'scanf',\
sprintf, 'sprintf', malloc, 'malloc', free, 'free'
import prosocks, CreateSocket, 'CreateSocket', ConnectSocket, 'ConnectSocket',\
CloseSocket, 'CloseSocket', FreeSocket, 'FreeSocket', AcceptSocket, 'AcceptSocket',\
ReadSocket, 'ReadSocket', WriteSocket, 'WriteSocket'
section '.data' data readable writeable
;Formatters
StringFormat db "%s", 13, 10, 0
StringExFormat db "%.*s", 13, 10, 0
ByteFormat db "%x", 13, 10, 0
AddressFormat db "%p", 13, 10, 0
NumberFormat db "%d", 13, 10, 0
ErrorFormat db "Error %s", 13, 10, 0
;Strings
CannotCreateSocket db "Cannot create socket.", 0
CannotConnectSocket db "Cannot connect socket.", 0
Host db "raw.githubusercontent.com", 0
RequestedFile db "Brandon-T/ProSocks/master/README.md", 0
;Formatted Strings
GetHeader db "GET /%s HTTP/1.1", 13, 10,\
"Host: %s", 13, 10,\
"Connection: close", 13, 10,\
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11", 13, 10,\
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 13, 10,\
"Accept-Language: en-US,en;q=0.8", 13, 10,\
"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7", 13, 10,\
"Cache-Control: no-cache", 13, 10, 13, 10, 0
struc sizeof [args]
{
common .args
sizeof.#. = $-.
}
struc SockInfo sock, ssl, ctx, address, type, timeout, port, connected, blockmode
{
.sock dd sock
.ssl dd ssl
.ctx dd ctx
.address dd address
.type dd type
.timeout dd timeout
.port dw port;
.connected db connected
.blockmode db blockmode
}
sizeof.SockInfo = 28
sockinfo SockInfo 0, 0, 0, 0, 0, 0, 0, 0, 0
buffer db 512 dup(0)
buffptr rd 0
section '.code' code readable executable
main:
push ebp
mov ebp,esp
mov [sockinfo.address], Host ;set address
mov [sockinfo.timeout], 0x9C4 ;set timeout - 2500ms
mov [sockinfo.port], 0x1BB ;set port - 463
mov [sockinfo.blockmode], 0x1 ;set blocking
push sockinfo
call [CreateSocket] ;Create a socket. bool __cdecl CreateSocket(SSLSocket* ssl_info);
add esp, 0x04
push eax
push CannotCreateSocket
call PrintError ;If there were any errors, print them and quit.
cmp eax, 0x00
je .quit
push sockinfo
call [ConnectSocket] ;Connect the socket. bool __cdecl ConnectSocket(SSLSocket* ssl_info);
add esp, 0x04
push eax
push CannotConnectSocket
call PrintError ;If there were any errors, print them and quit.
cmp eax, 0x00
je .quit
push Host
push RequestedFile
push GetHeader
push buffer
call [sprintf] ;Create the get header.
add esp, 0x10
push eax
push buffer
push sockinfo
call [WriteSocket]
add esp, 0x0C
;sub esp, 0x204
;mov dword[ebp + 0x04], esp
push Host
push RequestedFile
push GetHeader
push buffer ;push dword[ebp + 0x04]
call [sprintf]
add esp, 0x10
push eax
push buffer
push sockinfo
call [WriteSocket] ;Write the buffer to the socket.
push 0x4E20
push buffptr
call SafePtrAlloc ;Allocate a buffer for reading.
push 0x4E20
push dword[buffptr]
push sockinfo
call [ReadSocket] ;Read the headers into the buffer.
add esp, 0x0C
push dword[buffptr]
push StringFormat
call [printf] ;Print the buffer/headers
add esp, 0x08
push 0xD0
push dword[buffptr]
push sockinfo
call [ReadSocket] ;Read the response into the buffer
add esp, 0x0C
push dword[buffptr]
push eax
push StringExFormat
call [printf] ;Print the buffer/data
add esp, 0x0C
push buffptr
call SafePtrFree ;Free the allocated buffer.
.quit:
push sockinfo
call [FreeSocket]
add esp, 0x04
call [getchar]
mov esp, ebp
pop ebx
mov eax, 0x00
ret
PrintError:
push ebp
mov ebp, esp
cmp dword[ebp + 0x0C], 0x01
jne .print
mov eax, 0x01
jmp .end
.print:
push dword[ebp + 0x08]
push ErrorFormat
call [printf]
add esp, 0x08
mov eax, 0x00
.end:
mov esp, ebp
pop ebp
ret 0x08
;Allocates memory and stores the address in the first parameter.
SafePtrAlloc: ;Takes two parameters. First is the Pointer, second is the size to allocate.
push ebp
mov ebp, esp
mov edx, [ebp + 0x08] ;Pointer to be freed
push dword[edx] ;Free pointed to memory
call [free]
add esp, 0x04
push edx ;Save pointer
push dword[ebp + 0x0C] ;Size to allocate in bytes
call [malloc] ;Allocate n-amount
add esp, 0x04 ;Pop parameters
pop edx ;Restore edx
mov [edx], eax ;Move allocated address into edx
mov esp, ebp
pop ebp
retn 0x08
;Sets a pointer to nullptr after freeing its memory
SafePtrFree: ;Takes one parameter. A pointer to a block of memory to free.
push ebp
mov ebp, esp
mov eax, [ebp + 0x08] ;Move pointer into eax
mov edx, eax ;Copy pointer location
push edx ;Save copied pointer
push dword[eax] ;Push the pointed to address
call [free] ;Free the memory
add esp, 0x04
pop edx ;Restore the copied pointer
mov [edx], dword 0x0 ;Set it to nullptr
mov esp, ebp
pop ebp
ret 0x04
If Using Simba (ProSocks v0.2+):
GET:
Simba Code:
{$loadlib prosocks}
Function GetPageEx(URL: String): String;
var
S: SSLSocket;
res: ProMemoryStruct;
begin
//S.Timeout := 500; //custom timeout if needed.
Pro_InitSocket(S, nil, nil, nil, nil);
Pro_CreateSocket(S, '');
Pro_SetSSL(S, false, false, true);
Pro_SetURL(S, URL);
Pro_DoGetEx(S, res); //GetRequest
{$IFDEF LAPE}
SetLength(Result, res.size);
MemMove(res.memory^, Result[1], res.size);
{$ELSE}
Result := res.memory;
{$ENDIF}
try
Pro_FreeSocket(S);
except
WriteLn('Unable to Free ' + URL + ' ProSocks Error');
end;
end;
Advanced GET:
Simba Code:
//Letting Lape handle the memory allocations instead of the plugin
function PCharToStr(P: PChar): String;
var
L: Integer;
PP: PChar := P;
begin
while (PP^ <> #0) do
begin
Inc(PP); Inc(L);
end;
SetLength(Result, L + 1);
MemMove(P^, Result[1], L);
end;
Function Pro_CustomWriteF(contents: PChar; size: PtrUInt; nmemb: PtrUint; var userp: String): PtrUInt;
var
realsize: PtrUInt;
l: PtrUInt;
ptr: PChar;
begin
ptr := @userp;
realsize := size * nmemb;
if (size <> 0) then
begin
l := Length(UserP);
if (l = 0) then l := 1;
SetLength(UserP, Length(UserP) + realsize);
MemMove(Contents^, UserP[l], realsize); //<3 slacky.
end else
if (ptr <> nil) then
SetLength(UserP, 0);
Result := realsize;
end;
Function Pro_CustomErrorHandlerF(str: PChar; errorcode: LongInt): PtrUInt;
begin
writeln('Error: ' + PCharToStr(Str));
writeln('Error Code: ' + ToStr(ErrorCode));
end;
Function Pro_CustomStrLenF(var str: String): PtrUInt;
begin
Result := Length(str);
end;
var
S: SSLSocket;
Str: String;
begin
S.Timeout := 500; //custom timeout.
S.caller_allocates := true; //Lape allocates all strings and memory.
S.data := @Str; //String to be filled with returned data.
Pro_InitSocket(S, Natify(@Pro_CustomWriteF), Natify(@Pro_CustomWriteF), Natify(@Pro_CustomErrorHandlerF), Natify(@Pro_CustomStrLenF));
Pro_CreateSocket(S, '');
Pro_SetSSL(S, false, true);
Pro_SetURL(S, 'https://villavu.com/forum/');
Pro_DoGet(S);
Pro_FreeSocket(S);
writeln(Str);
end.
GET (Custom Headers):
Simba Code:
{$loadlib prosocks}
var
S: SSLSocket;
res: ProMemoryStruct;
begin
Pro_InitSocket(S, nil, nil, nil, nil);
Pro_CreateSocket(S, '');
Pro_SetSSL(S, false, false, true);
Pro_SetURL(S, 'https://villavu.com/forum/');
Pro_SetHeader(S, 'Accept', 'text/html', false); //custom header.
Pro_SetHeader(S, 'Connection', 'keep-alive', false); //custom header.
Pro_DoGetEx(S, res);
writeln(res.memory);
Pro_FreeSocket(S);
end.
POST (Cookie handling as well):
Simba Code:
{$loadlib prosocks}
var
S: SSLSocket;
MS: ProMemoryStruct;
begin
Pro_InitSocket(S, nil, nil, nil, nil);
Pro_CreateSocket(S, '');
Pro_SetCookies(S, 'Cookies.txt', 'Cookies.txt'); //allow cookies.
Pro_SetSSL(S, false, false, true);
Pro_SetURLFollow(S, true); //follow redirects.
Pro_SetURL(S, 'https://facebook.com');
Pro_DoGet(S); //dummy GET (used in the OAuth protocol)
Pro_SetURL(S, 'https://www.facebook.com/login.php?login_attempt=1&next=https%3A%2F%2Fwww.facebook.com%2Fmessages%2F');
Pro_AddParameter(S, 'id', 'login_form', false);
Pro_AddParameter(S, 'trynum', '1', false);
Pro_AddParameter(S, 'email', 'email@hotmail.com', false);
Pro_AddParameter(S, 'pass', '****', false);
Pro_DoPost(S);
Pro_SetURL(S, 'https://www.facebook.com/messages/'); //private page.. to test if we logged in successfully..
Pro_DoGetEx(S, MS);
writeln(MS.memory); //save to a file.html and open the file in the browser. ;)
Pro_FreeSocket(S);
end.
SMTP (Sending Emails.. Supports: CC, BCC, Attachments, MIME, etc..):
Simba Code:
{$loadlib prosocks}
var
S: SSLSocket;
begin
Pro_InitSocket(S, nil, nil, nil, nil); //nil for PS.
Pro_CreateSocket(S, ''); //default user agent.
Pro_SetVerbose(S, True); //debugging enabled. Not needed.
Pro_SetSSL(S, false, false, true);
Pro_SMTP(S, 'smtps://smtp.gmail.com', 'user@gmail.com', '****', 'Brandon T', 'to@gmail.com', 'cc', 'bcc', 'Subject', 'Message', 'text/plain; charset=UTF-8', 'Attachment.ext', 'application/x-msdownload; charset=UTF-8');
Pro_FreeSocket(S);
end.
POP3 (Receiving Emails):
Simba Code:
{$loadlib prosocks}
var
S: SSLSocket;
MS: ProMemoryStruct;
begin
Pro_InitSocket(S, nil, nil, nil, nil); //nil for PS.
Pro_CreateSocket(S, ''); //default user agent.
Pro_SetVerbose(S, True); //debugging enabled. Not needed.
Pro_SetSSL(S, false, false, true);
Pro_SetURL(S, 'pop.gmail.com');
Pro_SetLogin(S, 'MyEmail@gmail.com', 'MyPassword');
Pro_PerformEx(S, MS);
writeln(MS.memory); //Print results.
Pro_FreeSocket(S);
List of Available Functions & Definitions:
Simba Code:
type ProWritePtr = Function(contents: PChar; size: PtrUInt; nmemb: PtrUint; var userp: String): PtrUInt;
type ProErrorHandlerPtr = Function(str: PChar; errorcode: LongInt): PtrUInt;
type ProLenPtr = Function(var Str: String): PtrUInt;
{$IFNDEF LAPE}
type
ProMemoryStruct = record
memory: PChar;
size: PtrUInt;
end;
{$ELSE}
type
ProMemoryStruct = packed record
memory: PChar;
size: PtrUInt;
end;
{$ENDIF}
{$IFNDEF LAPE}
type
SSLSocket = record
curl_handle: PtrUInt;
headers: PChar;
data: PChar;
params: PChar;
LengthFunc: ProLenPtr;
ErrorHandlerFunc: ProErrorHandlerPtr;
WriteFunc: ProWritePtr;
HeaderFunc: ProWritePtr;
hdrs: PChar;
Timeout: Cardinal;
Port: Word;
caller_allocates: Boolean;
end;
{$ELSE}
type
SSLSocket = packed record
curl_handle: PtrUInt;
headers: PChar;
data: PChar;
params: PChar;
LengthFunc: ProLenPtr;
ErrorHandlerFunc: ProErrorHandlerPtr;
WriteFunc: ProWritePtr;
HeaderFunc: ProWritePtr;
hdrs: PChar;
Timeout: Cardinal;
Port: Word;
caller_allocates: Boolean;
end;
{$ENDIF}
//all parameters for this function are to be set to nil in pascal script (except the first parameter). That's because PS doesn't have "natify" or "native".
Procedure Pro_InitSocket(var curl_info: SSLSocket; WriteFunc: ProWritePtr; HeaderFunc: ProWritePtr; ErrorHandlerFunc: ProErrorHandlerPtr; StrLenFunc: ProLenPtr);
Procedure Pro_CreateSocket(var curl_info: SSLSocket; useragent: String);
Procedure Pro_FreeSocket(var curl_info: SSLSocket);
Procedure Pro_SetURLFollow(var curl_info: SSLSocket; follow: Boolean);
Procedure Pro_SetSSL(var curl_info: SSLSocket; try_set: Boolean; verifypeer: Boolean; verifyhost: Boolean);
Procedure Pro_SetCookies(var curl_info: SSLSocket; const cookiejar: String; const cookiefile: String);
Procedure Pro_SetHeaderCapture(var curl_info: SSLSocket; enable: boolean);
Function Pro_SetHeader(var curl_info: SSLSocket; const key: String; const value: String): Boolean;
Procedure Pro_CustomRequest(var curl_info: SSLSocket; const request: String);
Procedure Pro_SetNoBody(var curl_info: SSLSocket; enable: Boolean);
Procedure Pro_SetVerbose(var curl_info: SSLSocket; enable: Boolean);
Function Pro_GetHostLocation(var address: String; var buffer: String): String;
Function Pro_GetRequestLocation(var address: String; var buffer: String): String;
Procedure Pro_SetURL(var curl_info: SSLSocket; const URL: String);
Procedure Pro_SetUpload(var curl_info: SSLSocket; enable: Boolean);
Procedure Pro_SetLogin(var curl_info: SSLSocket; const user: String; const pwd: String);
Procedure Pro_ClearParameters(var curl_info: SSLSocket);
Function Pro_AddParameter(var curl_info: SSLSocket; const key: String; const value: String; escape: Boolean): Boolean;
Function Pro_DoGet(var curl_info: SSLSocket): PChar;
Procedure Pro_DoGetEx(var curl_info: SSLSocket; var Res: ProMemoryStruct);
Function Pro_DoPost(var curl_info: SSLSocket): PChar;
Procedure Pro_DoPostEx(var curl_info: SSLSocket; var Res: ProMemoryStruct);
Function Pro_Perform(var curl_info: SSLSocket): PChar;
Procedure Pro_PerformEx(var curl_info: SSLSocket; var Res: ProMemoryStruct);
Function Pro_GetHeaders(var curl_info: SSLSocket): PChar;
Procedure Pro_GetHeadersEx(var curl_info: SSLSocket; var Res: ProMemoryStruct);
Function Pro_SMTP(var curl_info: SSLSocket; url, user, pwd, name, recipient, cc, bcc, subject, body, bodymime, file, filemime: PChar): Boolean;
Procedure Pro_MSTPC(var curl_info: SSLSocket; var Res: ProMemoryStruct);
If using C/C++ (Prosocks v.0.2+):
C++ Code:
//// main.cpp// TestSSL//// Created by Brandon T on 2015-10-11.// Copyright © 2015 SRL. All rights reserved.//#include <dlfcn.h>#include <stdint.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#define LOAD_FUNC(MODULE, PTR) (PTR = (decltype(PTR))dlsym(MODULE, #PTR))int main
(int argc
, const char * argv
[]){ void* module
= dlopen
("/Users/Brandon/Desktop/libProSocks.dylib", RTLD_LAZY
); if (module
) { printf("All good\n"); LOAD_FUNC
(module
, Curl_InitSocket
); LOAD_FUNC
(module
, Curl_CreateSocket
); LOAD_FUNC
(module
, Curl_FreeSocket
); LOAD_FUNC
(module
, Curl_SetURLFollow
); LOAD_FUNC
(module
, Curl_SetSSL
); LOAD_FUNC
(module
, Curl_SetCookies
); LOAD_FUNC
(module
, Curl_SetHeaderCapture
); LOAD_FUNC
(module
, Curl_SetHeader
); LOAD_FUNC
(module
, Curl_CustomRequest
); LOAD_FUNC
(module
, Curl_SetNoBody
); LOAD_FUNC
(module
, Curl_SetVerbose
); LOAD_FUNC
(module
, Curl_SetVerbose
); LOAD_FUNC
(module
, Curl_GetHostLocation
); LOAD_FUNC
(module
, Curl_GetRequestLocation
); LOAD_FUNC
(module
, Curl_SetURL
); LOAD_FUNC
(module
, Curl_SetUpload
); LOAD_FUNC
(module
, Curl_SetLogin
); LOAD_FUNC
(module
, Curl_ClearParams
); LOAD_FUNC
(module
, Curl_AddParameter
); LOAD_FUNC
(module
, Curl_DoGet
); LOAD_FUNC
(module
, Curl_DoPost
); LOAD_FUNC
(module
, Curl_Perform
); LOAD_FUNC
(module
, Curl_GetHeaders
); LOAD_FUNC
(module
, Curl_SMTP
); CurlSock sock
= {0}; Curl_InitSocket
(&sock
, nullptr
, nullptr
, nullptr
, nullptr
); Curl_CreateSocket
(&sock
, ""); Curl_SetVerbose
(&sock
, true); Curl_SetSSL
(&sock
, false, false, true); Curl_SMTP
(&sock
, "smtps://smtp.gmail.com", "MyEmail@gmail.com", "MyPassword", "Brandon T", "Receipient@gmail.com", nullptr
, nullptr
, "Subject", "Message", "text/plain; charset=UTF-8", nullptr
, nullptr
); Curl_FreeSocket
(&sock
); dlclose
(module
); } else { printf("%s\n", dlerror
()); } return 0;}
Yup.. You can now use SSL and TLS without having to download addition crap. You can send emails directly from Simba, etc.. Gmail, Yahoo, AOL, Hotmail/Live/Outlook.. Anything..