Archive

Archive for March, 2015

Thoughts on Modern C++

March 28th, 2015 No comments

I’ve recently finished reading Effective Modern C++, which is the continuation of the “Effective C++” series for C++11/14. The book covered most of the newer features of modern C++ along with sufficient code examples to show their usage and applications. Overall, I’m pretty excited to see some of these features getting adopted in current and future C++ code bases. The motivation for a lot of these features naturally stemmed from the reasons of performance and efficiency, as is to be expected with anything C++ related.

Features such as auto, nullptr, constexpr, alias declarations, override, default/delete declarations, lambdas, smart pointers, and other features allow for smaller, cleaner, and in the case of some, less bug-prone code. At the same time, type traits, noexcept, rvalue/universal references and their move/forward semantics, allow for more efficient code generation and run-time performance gains.

However, some of these features are not without their pitfalls. For example, the auto keyword has some tricky pitfalls due to the rules of modern C++ type deduction.

    int x = 123;
    auto y{ 123 };
 
    std::cout
        << "type of x: " << typeid(x).name()
        << std::endl
        << "type of y " << typeid(y).name()
        << std::endl;

the output of the following code is

type of x: int
type of y class std::initializer_list < int >

and

    std::vector boolVec = { true, false, false, true, true, false };
 
    bool bSecondElem = boolVec[1];
    auto bSecondElemAuto = boolVec[1];
 
    std::cout
        << "type of bSecondElem: " << typeid(bSecondElem).name()
        << std::endl
        << "type of bSecondElemAuto " << typeid(bSecondElemAuto).name()
        << std::endl;

outputs

type of bSecondElem: bool
type of bSecondElemAuto class std::_Vb_reference < struct std::_Wrap_alloc  > >

These were explained away by stating the different rules of auto type deduction versus template type dedication the beginning of the book, or the pitfalls of auto type deduction when dealing with classes such as std::vector < bool >, which save space by storing a bit per item and provide a reference to a proxy object when their operator[] is invoked. There are other notable edge cases, such as passing arguments through braced initializers to forwarding templates (Item 30, along with other issues), possible problems of dangling references from using default-capture lambdas (Item 31), and others. Even given these, I’m still excited to use these features (where appropriate) and see the benefits that modern C++ brings.

Categories: Programming Tags:

Malware Techniques: Code Streaming

March 26th, 2015 No comments

This quick post will cover the topic of code streaming. For example, take malware. One way for malware to hide and persist on a system is to not contain any malicious code. This is done by getting the malicious payload through an external source, such as a direct request to a web server, a Twitter/social media post, a Pastebin, or any other common mechanism. This code, usually encrypted or obfuscated in some way, is then mapped in to the malicious process and executed. After execution, the memory region is cleaned up and reused or reallocated in order to carry out further malicious functionality. The code for this functionality looks pretty straightforward:

MemoryExecutor::MemoryExecutor(const size_t ulAllocSize)
    : m_ulAllocSize{ ulAllocSize }
{
    m_pMemory = std::unique_ptr(new char[ulAllocSize]);
}
 
const bool MemoryExecutor::MapToRegion(const char * const pBytes, const size_t ulSize)
{
    if (ulSize > m_ulAllocSize)
    {
        m_ulAllocSize = ulSize;
        m_pMemory = std::unique_ptr((char *)std::realloc(m_pMemory.get(), m_ulAllocSize));
        if (m_pMemory.get() == nullptr)
        {
            return false;
        }
    }
 
#ifdef DEBUG
    std::memset(m_pMemory.get(), 0xCC, ulSize);
#endif
 
    std::memcpy(m_pMemory.get(), pBytes, ulSize);
 
    DWORD_PTR dwOldProtect = 0;
    return BOOLIFY(VirtualProtect(m_pMemory.get(), ulSize, PAGE_EXECUTE_READWRITE, (PDWORD)dwOldProtect));
}
 
void MemoryExecutor::ExecuteRegion()
{
    using pFnc = void (*)();
    pFnc pRuntimeFunction = (pFnc)m_pMemory.get();
    pRuntimeFunction();
 
    memset(m_pMemory.get(), 0, m_ulAllocSize);
    m_pMemory.release();
}

with the intention that pBytes in MapToRegion contains the malicious buffer. However, there are a few issues that come up, such as how to make WinAPI calls. The three solutions that I’ve seen to this come up in the wild are

  • Map position-independent shellcode that traverses the DLL list and manually implements GetProcAddress. This is done by accessing the PEB structure created for each process. The PEB structure contains a pointer to a PEB_LDR_DATA structure, which in turn contains three lists: load order, memory order, and initialization order. These three lists contain all of the DLLs loaded in to the process via their base address. Once a base address for the desired DLL is obtained by traversing the list, it is possible to find its export section and traverse the export table. For an x86 assembly implementation, see here. This technique, in a mix of x86 and C, was also used by me in demonstrating how to write a file packer here.
  • Set up registers/arguments and perform the native syscall. For example, the implementation of NtTerminateProcess on x64 looks like:
NtTerminateProcess:
00007FF998AE1040 4C 8B D1             mov         r10,rcx  
00007FF998AE1043 B8 2B 00 00 00       mov         eax,2Bh  
00007FF998AE1048 0F 05                syscall  
00007FF998AE104A C3                   ret  

where the code in red is the syscall number. ThisĀ  approach is pretty volatile because syscall numbers can change across different Windows versions.

  • Get the addresses of the DLLs from within the malware, via GetModuleHandle, and fix up the addresses manually when they’re mapped. It’s pretty sloppy, but I’ve seen it before.

As far as stealth goes, something like the code above is pretty easy to detect. The idea of code executing off the heap (after allocating and changing the page permissions) does set off the red flags. Other implementations that I’ve seen have been to

  • Allocate executable pages upfront with VirtualAlloc. This is basically the same thing as above.
  • Locate empty blocks of memory in executable pages and map the code there. These empty blocks of memory usually occur due to alignment reasons in the code and can be exploited to store the malicious functionality. This approach is pretty convenient since the memory page(s) will already have the appropriate permissions, and when executed, won’t look as suspicious as when executing off the heap.
Categories: General x86, General x86-64, Programming Tags: