Skip to main content

直接与间接 Syscall

背景提取 syscall 号码


直接调用 Syscall


间接调用 Syscall




Hell's Gate

https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/ 

if (*((PBYTE)pFunctionAddress + cw) == 0x4c
					&& *((PBYTE)pFunctionAddress + 1 + cw) == 0x8b
					&& *((PBYTE)pFunctionAddress + 2 + cw) == 0xd1
					&& *((PBYTE)pFunctionAddress + 3 + cw) == 0xb8
					&& *((PBYTE)pFunctionAddress + 6 + cw) == 0x00
					&& *((PBYTE)pFunctionAddress + 7 + cw) == 0x00) {
					BYTE high = *((PBYTE)pFunctionAddress + 5 + cw); 
					BYTE low = *((PBYTE)pFunctionAddress + 4 + cw); 
					pVxTableEntry->wSystemCall = (high << 8) | low;
					break;
}
// Search the pattern mov r10,rcx mov eax
if (*((PBYTE)pFunctionAddress + cw) == 0x4c
	&& *((PBYTE)pFunctionAddress + 1 + cw) == 0x8b
	&& *((PBYTE)pFunctionAddress + 2 + cw) == 0xd1
	&& *((PBYTE)pFunctionAddress + 3 + cw) == 0xb8
	&& *((PBYTE)pFunctionAddress + 6 + cw) == 0x00
	&& *((PBYTE)pFunctionAddress + 7 + cw) == 0x00) 




Halo's Gate


int GoUp -32;
int GoDown 32;
// If the first instruction of the syscall is a an inconditional jump (aka it's hooked)
if (*((PBYTE)pFunctionAddress) == 0xe9) {
	// Search beginning pattern of syscall stub through 500 function up and down from our location
	for (WORD index = 1; index <= 500; index++) {
		// Search the begining of a syscall stub in the next function down
		if (*((PBYTE)pFunctionAddress + index * GoDown) == 0x4c
			&& *((PBYTE)pFunctionAddress + 1 + index * GoDown) == 0x8b
			&& *((PBYTE)pFunctionAddress + 2 + index * GoDown) == 0xd1
			&& *((PBYTE)pFunctionAddress + 3 + index * GoDown) == 0xb8
			&& *((PBYTE)pFunctionAddress + 6 + index * GoDown) == 0x00
			&& *((PBYTE)pFunctionAddress + 7 + index * GoDown) == 0x00) {
			BYTE high = *((PBYTE)pFunctionAddress + 5 + index * GoDown);
			BYTE low = *((PBYTE)pFunctionAddress + 4 + index * GoDown);
			// substract the index from the current syscall identifier to find the one of our target function
			pVxTableEntry->wSystemCall = (high << 8) | low - index;
			return TRUE;
		}
		// Search the begining of a syscall stub in the next function down
		if (*((PBYTE)pFunctionAddress + index * GoUp) == 0x4c
			&& *((PBYTE)pFunctionAddress + 1 + index * GoUp) == 0x8b
			&& *((PBYTE)pFunctionAddress + 2 + index * GoUp) == 0xd1
			&& *((PBYTE)pFunctionAddress + 3 + index * GoUp) == 0xb8
			&& *((PBYTE)pFunctionAddress + 6 + index * GoUp) == 0x00
			&& *((PBYTE)pFunctionAddress + 7 + index * GoUp) == 0x00) {
			BYTE high = *((PBYTE)pFunctionAddress + 5 + index * GoUp);
			BYTE low = *((PBYTE)pFunctionAddress + 4 + index * GoUp);
			// substract the index from the current syscall identifier to find the one of our target function
			pVxTableEntry->wSystemCall = (high << 8) | low + index;
			return TRUE;
		}
}


FreshyCalls

  //This function retrieve the RVA and name of "Nt" functions and put them in the sorted map
  //
  //We go trough the functions names in the Export Directory
  for (size_t i = 0; i < export_dir->NumberOfNames; i++) {
    function_name = reinterpret_cast<const char *>(ntdll_base + names_table[i]);

    // If the name of the function start with "Nt" and don't start with "Ntdll"
    // we retrieve the info
    if (function_name.rfind("Nt", 0) == 0 && function_name.rfind("Ntdll", 0) == std::string::npos) {
      stub_ordinal = names_ordinals_table[i];
      stub_address = ntdll_base + functions_table[stub_ordinal];
	  
	  // We put the RVA as a key and the function name as the value.
	  // This is a sorted map.
      // The elements are automatically sorted using the key value.
	  // This means that when all the Nt function will be loaded, 
      // the first element will be the Nt function with the lowest address 
      // and the last the one with the biggest address.
      stub_map.insert({stub_address, function_name});
    }
  }

  // `stub_map` is ordered from lowest to highest using the stub address. Syscalls numbers are
  // assigned using this ordering too. The lowest stub address will be the stub with the lowest
  // syscall number (0 in this case). We just need to iterate `stub_map` and iterate the syscall
  // number on every iteration.

  static inline void ExtractSyscallsNumbers() noexcept {
    uint32_t syscall_no = 0;
    // The stub_map filled previously in the code presented above
    for (const auto &pair: stub_map)  {
	  //Creation of a map associating function name and syscall identifier.
      syscall_map.insert({pair.second, syscall_no});
      syscall_no++;
    }
  };


SysWhisper2

    DWORD i = 0;
	/*
	//For info. It's in the header file.
	typedef struct _SW2_SYSCALL_ENTRY
	{
		DWORD Hash;
		DWORD Address;
	} SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY;
	
	#define SW2_MAX_ENTRIES 500
	*/
	
    PSW2_SYSCALL_ENTRY Entries = SW2_SyscallList.Entries;
    do
    {
        // Retrieve function name from the Dll.
        PCHAR FunctionName = SW2_RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]);

        // Check if the function name starts with "Zw"
        if (*(USHORT*)FunctionName == 'wZ')
        {
			// If yes, hash the name (for AV/EDR/Malware Analyst evasion reasons) and put it in an Entries element
            Entries[i].Hash = SW2_HashSyscall(FunctionName);
			// Put also the address of the function
            Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]];

            i++;
            if (i == SW2_MAX_ENTRIES) break;
        }
    } while (--NumberOfNames);

    // Save total number of system calls found.
    SW2_SyscallList.Count = i;

    // Sort the list by address in ascending order.
    for (i = 0; i < SW2_SyscallList.Count - 1; i++)
    {
        for (DWORD j = 0; j < SW2_SyscallList.Count - i - 1; j++)
        {
            if (Entries[j].Address > Entries[j + 1].Address)
            {
                // Swap entries.
                SW2_SYSCALL_ENTRY TempEntry;

                TempEntry.Hash = Entries[j].Hash;
                TempEntry.Address = Entries[j].Address;

                Entries[j].Hash = Entries[j + 1].Hash;
                Entries[j].Address = Entries[j + 1].Address;

                Entries[j + 1].Hash = TempEntry.Hash;
                Entries[j + 1].Address = TempEntry.Address;
            }
        }
    }

    return TRUE;
}


TartarusGate

https://trickster0.github.io/posts/Halo's-Gate-Evolves-to-Tartarus-Gate/