Read more about this technique HERE
Delphi
program IsDebuggerPresent;
{$APPTYPE CONSOLE}
uses
WinAPI.Windows, System.SysUtils;
begin
try
if IsDebuggerPresent() then
WriteLn('Process is currently getting debugged.')
else
WriteLn('Process is not likely getting debugged.');
readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Read more...
Read more about this technique HERE
Delphi
program OutputDebugString;
{$APPTYPE CONSOLE}
uses
WinAPI.Windows,
System.SysUtils;
var AErrorValue : Byte;
begin
try
randomize;
AErrorValue := Random(High(Byte));
SetLastError(AErrorValue);
OutputDebugStringW('TEST');
if (GetLastError() = AErrorValue) then
WriteLn('Debugger detected using OutputDebugString() technique.')
else
WriteLn('No debugger detected using OutputDebugString() technique.');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Read more...
Read more about this technique HERE
Delphi
program SuspendThread;
{$APPTYPE CONSOLE}
uses
WinAPI.Windows, System.SysUtils, Generics.Collections, tlHelp32, Classes;
type
TProcessItem = class
private
FName : String;
FProcessId : Cardinal;
FThreads : TList;
{@M}
procedure EnumThreads();
public
{@C}
constructor Create(AName : String; AProcessId : Cardinal; AEnumThreads : Boolean = True);
destructor Destroy(); override;
{@G}
property Name : String read FName;
property ProcessId : Cardinal read FProcessId;
property Threads : TList read FThreads;
end;
TEnumProcess = class
private
FItems : TObjectList;
public
{@C}
constructor Create();
destructor Destroy(); override;
{@M}
function Refresh() : Cardinal;
procedure Clear();
function Get(AProcessId : Cardinal) : TProcessItem; overload;
function Get(AName : String) : TProcessItem; overload;
{@G}
property Items : TObjectList read FItems;
end;
{
Import API's From Kernel32
}
const THREAD_SUSPEND_RESUME = $00000002;
function OpenThread(
dwDesiredAccess: DWORD;
bInheritHandle: BOOL;
dwThreadId: DWORD
) : THandle; stdcall; external kernel32 name 'OpenThread';
{
Global Vars
}
var LFindWindowSignatures : TDictionary;
LProcessNameSignatures : TStringList;
LProcesses : TEnumProcess;
{
Read more...
Read more about this technique HERE
Delphi
program FindWindowAPI;
{$APPTYPE CONSOLE}
uses
System.SysUtils, WinAPI.Windows, Generics.Collections, psAPI;
{
Read more...
Read more about this technique HERE
Delphi
unit UntPEBDebug;
interface
uses Windows;
const PROCESS_QUERY_LIMITED_INFORMATION = $1000;
PROCESS_BASIC_INFORMATION = 0;
// https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
var _NtQueryInformationProcess : function(
ProcessHandle : THandle;
ProcessInformationClass : DWORD;
ProcessInformation : Pointer;
ProcessInformationLength :
ULONG; ReturnLength : PULONG) : LongInt; stdcall;
hNTDLL : THandle;
{$IFDEF WIN64}
type
PProcessBasicInformation = ^TProcessBasicInformation;
TProcessBasicInformation = record
ExitStatus : Int64;
PebBaseAddress : Pointer;
AffinityMask : Int64;
BasePriority : Int64;
UniqueProcessId : Int64;
InheritedUniquePID : Int64;
end;
{$ELSE}
type
PProcessBasicInformation = ^TProcessBasicInformation;
TProcessBasicInformation = record
ExitStatus : DWORD;
PebBaseAddress : Pointer;
AffinityMask : DWORD;
BasePriority : DWORD;
UniqueProcessId : DWORD;
InheritedUniquePID : DWORD;
end;
{$ENDIF}
function GetProcessDebugStatus(AProcessID : Cardinal; var ADebugStatus : boolean) : Boolean;
function SetProcessDebugStatus(AProcessID : Cardinal; ADebugStatus : Boolean) : Boolean;
implementation
{-------------------------------------------------------------------------------
Open a process and retrieve the point of debug flag from PEB.
If function succeed, don't forget to call close process handle.
-------------------------------------------------------------------------------}
function GetDebugFlagPointer(AProcessID : Cardinal; var AProcessHandle : THandle) : Pointer;
var PBI : TProcessBasicInformation;
ARetLen : Cardinal;
begin
result := nil;
///
AProcessHandle := 0;
if NOT Assigned(_NtQueryInformationProcess) then
Exit();
///
AProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_WRITE or PROCESS_VM_READ, false, AProcessID);
if (AProcessHandle = 0) then
Exit;
if _NtQueryInformationProcess(AProcessHandle, PROCESS_BASIC_INFORMATION, @PBI, sizeOf(TProcessBasicInformation), @ARetLen) = ERROR_SUCCESS then
result := Pointer(NativeUInt(PBI.PebBaseAddress) + (SizeOf(Byte) * 2))
else
CloseHandle(AProcessHandle);
end;
{-------------------------------------------------------------------------------
Retrieve the target process debug status from PEB.
ADebugStatus = True : Target process debug flag is set.
ADebugStatus = False : Target process debug flag is not set.
-------------------------------------------------------------------------------}
function GetProcessDebugStatus(AProcessID : Cardinal; var ADebugStatus : boolean) : Boolean;
var hProcess : THandle;
pDebugFlagOffset : Pointer;
pDebugFlag : pByte;
ABytesRead : SIZE_T;
begin
result := false;
///
pDebugFlagOffset := GetDebugFlagPointer(AProcessID, hProcess);
if not Assigned(pDebugFlagOffset) then
Exit();
///
try
getMem(pDebugFlag, sizeOf(Byte));
try
if NOT ReadProcessMemory(hProcess, pDebugFlagOffset, pDebugFlag, sizeOf(Byte), ABytesRead) then
Exit;
///
ADebugStatus := (pDebugFlag^ = 1);
finally
FreeMem(pDebugFlag);
end;
///
result := (ABytesRead = SizeOf(Byte));
finally
CloseHandle(hProcess);
end;
end;
{-------------------------------------------------------------------------------
Update target process debug flag.
ADebugStatus = True : Set target process debug flag.
ADebugStatus = False : Unset target process debug flag.
-------------------------------------------------------------------------------}
function SetProcessDebugStatus(AProcessID : Cardinal; ADebugStatus : Boolean) : Boolean;
var hProcess : THandle;
pDebugFlagOffset : Pointer;
ADebugFlag : Byte;
ABytesWritten : SIZE_T;
begin
result := false;
///
pDebugFlagOffset := GetDebugFlagPointer(AProcessID, hProcess);
if not Assigned(pDebugFlagOffset) then
Exit();
///
try
if ADebugStatus then
ADebugFlag := 1
else
ADebugFlag := 0;
if NOT WriteProcessMemory(hProcess, pDebugFlagOffset, @ADebugFlag, SizeOf(Byte), ABytesWritten) then
Exit;
///
result := (ABytesWritten = SizeOf(Byte));
finally
CloseHandle(hProcess);
end;
end;
initialization
{
Load NtQueryInformationProcess from NTDLL.dll
}
_NtQueryInformationProcess := nil;
hNTDLL := LoadLibrary('ntdll.dll');
if (hNTDLL <> 0) then
@_NtQueryInformationProcess := GetProcAddress(hNTDLL, 'NtQueryInformationProcess');
finalization
_NtQueryInformationProcess := nil;
if (hNTDLL <> 0) then
FreeLibrary(hNTDLL);
end.
Read more...
Assignment Goals (SLAE-1530)
1) Create a TCP Bindshell Shellcode for Linux x86-32.
2) The port number should be easily configurable.
3) Bonus if getting referenced in exploit-db or shell-storm.
TCP Bindshell Principle
In few words, a TCP Bindshell is a tiny server program that waits for new clients on a specific port.
When a new client connects to the server it will spawn a new shell (Ex: /bin/bash
or /bin/sh
) and "binds" its file descriptors stdin
(0) stdout
(1) stderr
(2) to the new client socket.
Yes, a socket is nothing more than a file.
One infamous method to easily create a bindshell is to use Netcat
as following:
root@local:# mknod /tmp/backpipe p && /bin/sh 0</tmp/backpipe | nc -lvp 443 1>/tmp/backpipe
When you connect to port 443
(with any dumb client program ex: Netcat
, Telnet
) you will get remote control over shell instance.
user@local:$ nc 127.0.0.1 443
Assignment Goals (SLAE-1530)
-
Create a custom crypter like the one shown in the "crypters" video
-
Free to use any existing encryption schema
-
Can use any programming language
What is the purpose of a Crypter
A crypter is very close to encoders. It is a tiny application designed to encrypt a payload and decrypt the payload at runtime.
The payload is encrypted and embedded inside a host program often called a stub, when the stub is executed, it will decrypt the encrypted payload and redirect execution flow at decrypted payload address. Sometimes execution flow is not redirected but instead a new thread or a new process is created to host the payload execution.
Conversely to encoders, crypters uses complexes encryptions schema (RC4, AES, Blowfish, Camelia etc...) to keep the payload obfuscated. Each time a stub is generated, the encrypted payload will look completely different, it is a good solution to beat signature based detection systems.
Because of their complexity, crypters are often coded with higher level language such as C/C++, Delphi, .NET etc..
Read more...Assignment Goals ( SLAE-1530)
-
Take up 3 shellcodes from Shell-Storm and create polymorphic versions of them to beat pattern matching.
-
The polymorphic versions cannot be larger 150% of the existing shellcode.
-
Bonus points for making it shorter in length than original.
Foreword
On Shell-Storm, you will not always find the original assembly code for shellcodes you choose. To solve this issue, we've created a tiny Python script to convert a shellcode from its string form to raw format (stdout). We can easily pipe output result to Ndisasm
and recover an assembly code very close to the original version.
Assignment Goals (SLAE-1530)
-
Take up at least 3 shellcode samples created using Msfpayload for Linux/x86.
-
Use GDB/Ndisasm/Libemu to dissect the functionality of the shellcode.
-
Present your analysis.
Shellcode Candidates
We will use Msfvenom
from Metasploit Framework to generate three different payloads for Linux x86-32.
We can easily enumerate payloads for this architecture and operating system using the following command:
local@user:$ msfvenom -l payloads | grep "linux/x86"
We decided to use the three following payloads:
linux/x86/read_file
linux/x86/chmod
linux/x86/exec
Assignment Goals (SLAE-1530)
-
Create a custom encoding scheme.
-
PoC with using execve-stack as the shellcode.
Creating our own encoder
Shellcode encoders are useful for two main reasons:
- Minimize the risk of getting cough by detection systems.
- Avoid bad characters from our original shellcode.
An encoder take a shellcode in input and output a different looking shellcode without affecting it functionality.
The main disadvantage with encoding is that your shellcode size will naturally increase.
Read more...