Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,39 @@ It performs a bunch of common malware tricks with the goal of seeing if you stay

![Logo](https://i.imgur.com/jEFhsJT.png)

### Usage
```
$ ./al-khaser.exe -h
Usage: al-khaser.exe [OPTIONS]
Options:
--check <type> Enable specific check(s). Can be used multiple times. Valid types are:
TLS (Thread Local Storage callback checks)
DEBUG (Anti-debugging checks)
INJECTION (Code injection checks)
GEN_SANDBOX (Generic sandbox checks)
VBOX (VirtualBox detection)
VMWARE (VMware detection)
VPC (Virtual PC detection)
QEMU (QEMU detection)
KVM (KVM detection)
XEN (Xen detection)
WINE (Wine detection)
PARALLELS (Parallels detection)
HYPERV (Hyper-V detection)
CODE_INJECTIONS (Additional code injection techniques)
TIMING_ATTACKS (Timing/sleep-based sandbox evasion)
DUMPING_CHECK (Dumping memory/process checks)
ANALYSIS_TOOLS (Analysis tools detection)
ANTI_DISASSM (Anti-disassembly checks)
--sleep <seconds> Set sleep/delay duration in seconds (default: 600).
--delay <seconds> Alias for --sleep.
-h, --help Show this help message and exit.

Examples:
al-khaser.exe --check DEBUG --check TIMING_ATTACKS --sleep 30
al-khaser.exe --check VMWARE --check QEMU
al-khaser.exe --sleep 30
```

## Download

Expand Down
361 changes: 218 additions & 143 deletions al-khaser/Al-khaser.cpp

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions al-khaser/AntiAnalysis/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,13 @@ VOID analysis_tools_process()
{
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking process of malware analysis tool: %s "), szProcesses[i]);
if (GetProcessIdFromName(szProcesses[i]))
if (GetProcessIdFromName(szProcesses[i])) {
print_results(TRUE, msg);
else
stats_record(CAT_ANALYSIS_TOOLS, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_ANALYSIS_TOOLS, FALSE);
}
}
}
42 changes: 34 additions & 8 deletions al-khaser/AntiVM/Generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ VOID loaded_dlls()

/* Check if process loaded modules contains the blacklisted dll */
hDll = GetModuleHandle(szDlls[i]);
if (hDll == NULL)
if (hDll == NULL){
print_results(FALSE, msg);
else
stats_record(CAT_GEN_SANDBOX, FALSE);
}
else {
print_results(TRUE, msg);
stats_record(CAT_GEN_SANDBOX, TRUE);
}
}
}

Expand Down Expand Up @@ -82,19 +86,27 @@ VOID known_file_names() {
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking if process file name contains: %s "), szFilenames[i]);

/* Check if file name matches any blacklisted filenames */
if (StrCmpIW(szFilenames[i], szFileName) != 0)
if (StrCmpIW(szFilenames[i], szFileName) != 0) {
print_results(FALSE, msg);
else
stats_record(CAT_GEN_SANDBOX, FALSE);
}
else {
print_results(TRUE, msg);
stats_record(CAT_GEN_SANDBOX, TRUE);
}
}

// Some malware do check if the file name is a known hash (like md5 or sha1)
PathRemoveExtensionW(szFileName);
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking if process file name looks like a hash: %s "), szFileName);
if ((wcslen(szFileName) == 32 || wcslen(szFileName) == 40 || wcslen(szFileName) == 64) && IsHexString(szFileName))
if ((wcslen(szFileName) == 32 || wcslen(szFileName) == 40 || wcslen(szFileName) == 64) && IsHexString(szFileName)) {
print_results(TRUE, msg);
else
stats_record(CAT_GEN_SANDBOX, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_GEN_SANDBOX, FALSE);
}
}

static TCHAR* get_username() {
Expand Down Expand Up @@ -171,6 +183,8 @@ VOID known_usernames() {
}

print_results(matched, msg);
stats_record(CAT_GEN_SANDBOX, matched);

}

free(username);
Expand Down Expand Up @@ -262,6 +276,8 @@ VOID known_hostnames() {
}

print_results(matched, msg);
stats_record(CAT_GEN_SANDBOX, matched);

}

free(NetBIOSHostName);
Expand Down Expand Up @@ -300,18 +316,21 @@ VOID other_known_sandbox_environment_checks() {
matched = TRUE;
}
print_results(matched, (TCHAR*)_T("Checking whether username is 'Wilber' and NetBIOS name starts with 'SC' or 'SW' "));
stats_record(CAT_GEN_SANDBOX, matched);

matched = FALSE;
if ((0 == StrCmp(username, _T("admin"))) && (0 == StrCmp(NetBIOSHostName, _T("SystemIT")))) {
matched = TRUE;
}
print_results(matched, (TCHAR*)_T("Checking whether username is 'admin' and NetBIOS name is 'SystemIT' "));
stats_record(CAT_GEN_SANDBOX, matched);

matched = FALSE;
if ((0 == StrCmp(username, _T("admin"))) && (0 == StrCmp(DNSHostName, _T("KLONE_X64-PC")))) {
matched = TRUE;
}
print_results(matched, (TCHAR*)_T("Checking whether username is 'admin' and DNS hostname is 'KLONE_X64-PC' "));
stats_record(CAT_GEN_SANDBOX, matched);

matched = FALSE;
if ((0 == StrCmp(username, _T("John"))) &&
Expand All @@ -320,6 +339,7 @@ VOID other_known_sandbox_environment_checks() {
matched = TRUE;
}
print_results(matched, (TCHAR*)_T("Checking whether username is 'John' and two sandbox files exist "));
stats_record(CAT_GEN_SANDBOX, matched);

matched = FALSE;
if ((is_FileExists((TCHAR*)_T("C:\\email.doc"))) &&
Expand All @@ -329,6 +349,7 @@ VOID other_known_sandbox_environment_checks() {
matched = TRUE;
}
print_results(matched, (TCHAR*)_T("Checking whether four known sandbox 'email' file paths exist "));
stats_record(CAT_GEN_SANDBOX, matched);

matched = FALSE;
if ((is_FileExists((TCHAR*)_T("C:\\a\\foobar.bmp"))) &&
Expand All @@ -337,6 +358,7 @@ VOID other_known_sandbox_environment_checks() {
matched = TRUE;
}
print_results(matched, (TCHAR*)_T("Checking whether three known sandbox 'foobar' files exist "));
stats_record(CAT_GEN_SANDBOX, matched);

free(username);
free(NetBIOSHostName);
Expand Down Expand Up @@ -2249,9 +2271,13 @@ VOID looking_glass_vdd_processes()
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking processes %s "), szProcesses[i]);

if (GetProcessIdFromName(szProcesses[i]))
if (GetProcessIdFromName(szProcesses[i])) {
print_results(TRUE, msg);
else
stats_record(CAT_GEN_SANDBOX, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_GEN_SANDBOX, FALSE);
}
}
}
16 changes: 12 additions & 4 deletions al-khaser/AntiVM/KVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ VOID kvm_reg_keys()
{
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);
if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i])) {
print_results(TRUE, msg);
else
stats_record(CAT_KVM, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_KVM, FALSE);
}
}
}

Expand Down Expand Up @@ -70,10 +74,14 @@ VOID kvm_files()
PathCombine(szPath, szWinDir, szPaths[i]);
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking file %s "), szPath);
if (is_FileExists(szPath))
if (is_FileExists(szPath)) {
print_results(TRUE, msg);
else
stats_record(CAT_KVM, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_KVM, FALSE);
}
}

if (IsWoW64()) {
Expand Down
16 changes: 12 additions & 4 deletions al-khaser/AntiVM/Parallels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ VOID parallels_reg_keys()
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);

if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i])) {
print_results(TRUE, msg);
else
stats_record(CAT_PARALLELS, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_PARALLELS, FALSE);
}
}
}

Expand All @@ -43,10 +47,14 @@ VOID parallels_process()
{
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking Parallels processes: %s"), szProcesses[i]);
if (GetProcessIdFromName(szProcesses[i]))
if (GetProcessIdFromName(szProcesses[i])) {
print_results(TRUE, msg);
else
stats_record(CAT_PARALLELS, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_PARALLELS, FALSE);
}
}
}

Expand Down
32 changes: 24 additions & 8 deletions al-khaser/AntiVM/Qemu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ VOID qemu_reg_key_value()
{
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szEntries[i][0]);
if (Is_RegKeyValueExists(HKEY_LOCAL_MACHINE, szEntries[i][0], szEntries[i][1], szEntries[i][2]))
if (Is_RegKeyValueExists(HKEY_LOCAL_MACHINE, szEntries[i][0], szEntries[i][1], szEntries[i][2])) {
print_results(TRUE, msg);
else
stats_record(CAT_QEMU, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_QEMU, FALSE);
}
}
}

Expand All @@ -46,10 +50,14 @@ VOID qemu_reg_keys()
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking reg key %s "), szKeys[i]);

if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i]))
if (Is_RegKeyExists(HKEY_LOCAL_MACHINE, szKeys[i])) {
print_results(TRUE, msg);
else
stats_record(CAT_QEMU, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_QEMU, FALSE);
}
}
}

Expand All @@ -70,10 +78,14 @@ VOID qemu_processes()
{
TCHAR msg[256] = _T("");
_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking qemu processes %s "), szProcesses[i]);
if (GetProcessIdFromName(szProcesses[i]))
if (GetProcessIdFromName(szProcesses[i])) {
print_results(TRUE, msg);
else
stats_record(CAT_QEMU, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_QEMU, FALSE);
}
}
}

Expand Down Expand Up @@ -103,10 +115,14 @@ VOID qemu_dir()
PathCombine(szPath, szProgramFile, szDirectories[i]);

_stprintf_s(msg, sizeof(msg) / sizeof(TCHAR), _T("Checking QEMU directory %s "), szPath);
if (is_DirectoryExists(szPath))
if (is_DirectoryExists(szPath)) {
print_results(TRUE, msg);
else
stats_record(CAT_QEMU, TRUE);
}
else {
print_results(FALSE, msg);
stats_record(CAT_QEMU, FALSE);
}
}
}

Expand Down
Loading