Portcullis Labs » BRC https://labs.portcullis.co.uk Research and Development en-US hourly 1 http://wordpress.org/?v=3.8.5 Using Intel Pin tools for binary instrumentation https://labs.portcullis.co.uk/blog/using-intel-pin-tools-for-binary-instrumentation/ https://labs.portcullis.co.uk/blog/using-intel-pin-tools-for-binary-instrumentation/#comments Tue, 04 Nov 2014 16:03:01 +0000 https://labs.portcullis.co.uk/?p=4131 This article is continues the topic on dynamic instrumentation that it was presented before in a previous article. Yama LSM In this post, the basics of coding Intel Pin tools will be presented, but before we discuss this, you should be aware that a Linux Security Module exists that prevents binary instrumentation by default. Yama […]

The post Using Intel Pin tools for binary instrumentation appeared first on Portcullis Labs.

]]>
This article is continues the topic on dynamic instrumentation that it was presented before in a previous article.

Yama LSM

In this post, the basics of coding Intel Pin tools will be presented, but before we discuss this, you should be aware that a Linux Security Module exists that prevents binary instrumentation by default. Yama is a Linux Security Module that collects a number of system-wide DAC security protections that are not handled by the core kernel itself. Yama is controlled using sysctl. A description of some of the possible values for /proc/sys/kernel/yama/ptrace_scope is provided below:

  • 0 => Classic ptrace: a process can PTRACE_ATTACH to any other process running under the same uid, as long as it is dumpable.
  • 1 => Restricted ptrace: a process can only PTRACE_ATTACH only its descendants although an inferior can call prctl(PR_SET_PTRACER, debugger, …) to allow the debugger to call PTRACE_ATTACH.
  • 2 => Admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace with PTRACE_ATTACH
  • 3 => No attach: no processes may use ptrace with PTRACE_ATTACH nor via PTRACE_TRACEME.

For detailed information, visit the Linux kernel documentation about Yama.

Continuing with the Pin topic, it should be noted that if a Pin tool is executed without setting /proc/sys/kernel/yama/ptrace_scope to 0, the following message will appear:

$ ../pin/pin -t obj-intel64/check_pc_sections.so -- /bin/ls
E:Attach to pid 9495 failed.
E:  The Operating System configuration prevents Pin from using the default (parent) injection mode.
E:  To resolve this, either execute the following (as root):
E:  $ echo 0 > /proc/sys/kernel/yama/ptrace_scope
E:  Or use the "-injection child" option.
E:  For more information, regarding child injection, see Injection section in the Pin User Manual.
E:
Terminado (killed)

To allow debugging of inferior processes the value of /proc/sys/kernel/yama/ptrace_scope needs to be changed using sysctl:

# sysctl kernel.yama.ptrace_scope=0
kernel.yama.ptrace_scope = 0

Pin tools

The Pin tools are the tools created using Pin and used to perform program analysis on user space. Pin tools that perform the binary instrumentation have two key components:

  1. The instrumentation callback routine: a mechanism that decides if and where to inject calls to analysis functions; and
  2. The analysis function: code to execute at insertion points.

Note that the Pin tools are able to control a program starting with the very first instruction, meaning that it is possible even to inspect the linker’s code of a binary loading shared libraries. This could be utilised to perform run-time bug hunting in the operating system linker. Also, when programming Pin tools, it should be kept in mind that as the Pin documentation specifies, it is more important to tune the analysis code than the instrumentation code. This is because the instrumentation is executed once, but analysis code is called many times.

Executable Images and Sections

Pin provides access to the binary’s images and image sections using linked lists. Those lists can be traversed using the API calls APP_ImgHead(), App_ImgTail(), IMG_Valid(IMG x), IMG_Next(IMG x) and IMG_Previous(IMG x); additionally, a number a API functions exist for accessing image properties such as name, size, type, start address, etc. A detailed view of the image API can be examined in the image API documentation.

The image sections have the equivalent API functions to traverse the linked list: IMG_SecHead(IMG x),IMG_SecTail(IMG x), SEC_Valid(sec x), SEC_Prev(sec x), SEC_Next(sec x), SEC_Address (SEC sec), SEC_Valid (SEC x), etc. The complete list can be found in the section API documentation.

To illustrate the usage of the image and section API an example is provided:

#include "pin.H"
#include <iostream>
#include <fstream>
#include <string.h>

// =====================================================================
// Usage
// =====================================================================

INT32 Usage()
{
    cerr << "[*] This Pin tool prints the images and section names of a binary when loading" << endl;
    return -1;
}

// =====================================================================
// Analysis routines
// =====================================================================

// Prints image and section name, type and address
VOID loadImageSec(IMG img, VOID *v)
{
    UINT64 sec_cont = 0;
    string img_type;
    string sec_type;

    switch (IMG_Type(img)){
        case IMG_TYPE_STATIC:
            img_type = "static";
            break;
        case IMG_TYPE_SHARED:
            img_type = "shared";
            break;
        case IMG_TYPE_SHAREDLIB:
            img_type = "shared library";
            break;
        case IMG_TYPE_RELOCATABLE:
            img_type = "relocatable";
            break;
        default:
            img_type = "unknown";
    }

    cout << "[*] Loading image " << IMG_Name(img).c_str();
    cout << " @ " << StringFromAddrint(IMG_StartAddress(img));
    cout << " type " << img_type << endl;

    for (SEC sec=IMG_SecHead(img); SEC_Valid(sec); sec=SEC_Next(sec)) {
        if (strcmp(SEC_Name(sec).c_str(),"")) {

            switch (SEC_Type(sec)){
                case SEC_TYPE_REGREL:
                    sec_type = "relocations";
                    break;
                case SEC_TYPE_DYNREL:
                    sec_type = "dynamic relocations";
                    break;
                case SEC_TYPE_EXEC:
                    sec_type = "code";
                    break;
                case SEC_TYPE_DATA:
                    sec_type = "initialized data";
                    break;
                case SEC_TYPE_BSS:
                    sec_type = "unitialized data";
                    break;
                case SEC_TYPE_LOOS:
                    sec_type = "operating system specific";
                    break;
                case SEC_TYPE_USER:
                    sec_type = "user application specific";
                    break;
                default:
                    sec_type = "unknown";
            }

            cout << "\t => Loading section " << SEC_Name(sec).c_str();
            cout << " @ " << StringFromAddrint(SEC_Address(sec));
            cout << " type " << sec_type << endl;

            sec_cont++;
        }
    }

    cout << "[*] Done loading " << IMG_Name(img).c_str() << ": " << sec_cont << " sections" << endl;

}

// =====================================================================
// Main
// =====================================================================

int main(int argc, char *argv[])
{

    if(PIN_Init(argc,argv)) {
        return Usage();
    }

    cout << "[*] Executing Pin tool" << endl;
    cout << "[*] Adding instrumentation functions" << endl;
    IMG_AddInstrumentFunction(loadImageSec, 0);

    cout << "[*] Executing target program" << endl;
    PIN_StartProgram();

    return 0;
}
// EOF

To compile the Pin tool, save the code as load_bin_img_sec.cpp and execute the following cmd line on the custom development directory as explained in the previous article:

~/mytools $ ./build.sh
[*] Building load_bin_img_sec.cpp
g++ -DBIGARRAY_MULTIPLIER=1 -DUSING_XED -Wall -Werror -Wno-unknown-pragmas -fno-stack-protector -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX  -I../pin/source/include/pin -I../pin/source/include/pin/gen -I../pin/extras/components/include -I../pin/extras/xed2-intel64/include -I../pin/source/tools/InstLib -O3 -fomit-frame-pointer -fno-strict-aliasing   -c -o obj-intel64/load_bin_img_sec.o load_bin_img_sec.cpp
g++ -shared -Wl,--hash-style=sysv -Wl,-Bsymbolic -Wl,--version-script=../pin/source/include/pin/pintool.ver    -o obj-intel64/load_bin_img_sec.so obj-intel64/load_bin_img_sec.o  -L../pin/intel64/lib -L../pin/intel64/lib-ext -L../pin/intel64/runtime/glibc -L../pin/extras/xed2-intel64/lib -lpin -lxed -ldwarf -lelf -ldl
[*] Exec ../pin/pin -t obj-intel64/load_bin_img_sec.so -- <program>

The binary /bin/ls is taken as example target binary for the execution of compiled Pin tool:

~/mytools $ ../pin/pin -t obj-intel64/load_bin_img_sec.so -- /bin/ls /tmp/
[*] Executing PIN tool
[*] Adding instrumentation functions
[*] Executing target program
[*] Loading image /usr/bin/ls @ 0x00007f55b8798000 type shared
	 => Loading section .interp @ 0x0000000000400238 type initialized data
	 => Loading section .note.ABI-tag @ 0x0000000000400254 type initialized data
	 => Loading section .note.gnu.build-id @ 0x0000000000400274 type initialized data
	 => Loading section .dynsym @ 0x0000000000400350 type unknown
	 => Loading section .dynstr @ 0x0000000000400f50 type unknown
	 => Loading section .rela.dyn @ 0x0000000000401670 type relocations
	 => Loading section .rela.plt @ 0x0000000000401718 type relocations
	 => Loading section .init @ 0x0000000000402180 type code
	 => Loading section .plt @ 0x00000000004021a0 type code
	 => Loading section .text @ 0x00000000004028a0 type code
	 => Loading section .fini @ 0x0000000000411d4c type code
	 => Loading section .rodata @ 0x0000000000411d60 type initialized data
	 => Loading section .eh_frame_hdr @ 0x0000000000416e7c type initialized data
	 => Loading section .eh_frame @ 0x0000000000417588 type initialized data
	 => Loading section .init_array @ 0x0000000000619df0 type initialized data
	 => Loading section .fini_array @ 0x0000000000619df8 type initialized data
	 => Loading section .jcr @ 0x0000000000619e00 type initialized data
	 => Loading section .dynamic @ 0x0000000000619e08 type unknown
	 => Loading section .got @ 0x0000000000619ff8 type unknown
	 => Loading section .got.plt @ 0x000000000061a000 type initialized data
	 => Loading section .data @ 0x000000000061a3a0 type initialized data
	 => Loading section .bss @ 0x000000000061a600 type unitialized data
	 => Loading section .comment @ 0x0000000000000000 type unknown
	 => Loading section .shstrtab @ 0x0000000000000000 type unknown
[*] Done loading /usr/bin/ls: 24 sections
[*] Loading image /lib64/ld-linux-x86-64.so.2 @ 0x00007f55b8788000 type shared library
	 => Loading section .note.gnu.build-id @ 0x00007f55cb9201c8 type initialized data
	 => Loading section .hash @ 0x00007f55cb9201f0 type unknown
	 => Loading section .dynsym @ 0x00007f55cb920470 type unknown
	 => Loading section .dynstr @ 0x00007f55cb920710 type unknown
	 => Loading section .rela.dyn @ 0x00007f55cb920988 type relocations
	 => Loading section .rela.plt @ 0x00007f55cb920ac0 type relocations
	 => Loading section .plt @ 0x00007f55cb920b50 type code
	 => Loading section .text @ 0x00007f55cb920bc0 type code
	 => Loading section .rodata @ 0x00007f55cb939100 type initialized data
	 => Loading section .eh_frame_hdr @ 0x00007f55cb93d300 type initialized data
	 => Loading section .eh_frame @ 0x00007f55cb93d950 type initialized data
	 => Loading section .data.rel.ro @ 0x00007f55cbb40ba0 type initialized data
	 => Loading section .dynamic @ 0x00007f55cbb40e10 type unknown
	 => Loading section .got @ 0x00007f55cbb40fa0 type unknown
	 => Loading section .data @ 0x00007f55cbb41000 type initialized data
	 => Loading section .bss @ 0x00007f55cbb41fa0 type unitialized data
	 => Loading section .comment @ 0x0000000000000000 type unknown
	 => Loading section .shstrtab @ 0x0000000000000000 type unknown
	 => Loading section .symtab @ 0x0000000000000000 type unknown
	 => Loading section .strtab @ 0x0000000000000000 type unknown
[*] Done loading /lib64/ld-linux-x86-64.so.2: 20 sections
[*] Loading image /usr/lib/libcap.so.2 @ 0x00007f55b7c50000 type shared library
	 => Loading section .note.gnu.build-id @ 0x00007f55b84a8190 type initialized data
	 => Loading section .dynsym @ 0x00007f55b84a82b0 type unknown
	 => Loading section .dynstr @ 0x00007f55b84a8898 type unknown
	 => Loading section .rela.dyn @ 0x00007f55b84a8c30 type relocations
	 => Loading section .rela.plt @ 0x00007f55b84a9080 type relocations
	 => Loading section .init @ 0x00007f55b84a9350 type code
	 => Loading section .plt @ 0x00007f55b84a9370 type code
	 => Loading section .text @ 0x00007f55b84a9560 type code
	 => Loading section .fini @ 0x00007f55b84aac54 type code
	 => Loading section .rodata @ 0x00007f55b84aac60 type initialized data
	 => Loading section .eh_frame_hdr @ 0x00007f55b84aaf48 type initialized data
	 => Loading section .eh_frame @ 0x00007f55b84ab060 type initialized data
	 => Loading section .init_array @ 0x00007f55b86ab648 type initialized data
	 => Loading section .fini_array @ 0x00007f55b86ab650 type initialized data
	 => Loading section .jcr @ 0x00007f55b86ab658 type initialized data
	 => Loading section .dynamic @ 0x00007f55b86ab660 type unknown
	 => Loading section .got @ 0x00007f55b86ab840 type unknown
	 => Loading section .got.plt @ 0x00007f55b86ab870 type initialized data
	 => Loading section .data @ 0x00007f55b86ab980 type initialized data
	 => Loading section .bss @ 0x00007f55b86abac8 type unitialized data
	 => Loading section .comment @ 0x0000000000000000 type unknown
	 => Loading section .shstrtab @ 0x0000000000000000 type unknown
[*] Done loading /usr/lib/libcap.so.2: 22 sections
[*] Loading image /usr/lib/libacl.so.1 @ 0x00007f55b7c48000 type shared library
	 => Loading section .note.gnu.build-id @ 0x00007f55b82881c8 type initialized data
	 => Loading section .dynsym @ 0x00007f55b82884f8 type unknown
	 => Loading section .dynstr @ 0x00007f55b8288ed0 type unknown
	 => Loading section .rela.dyn @ 0x00007f55b8289580 type relocations
	 => Loading section .rela.plt @ 0x00007f55b8289700 type relocations
	 => Loading section .init @ 0x00007f55b8289cb8 type code
	 => Loading section .plt @ 0x00007f55b8289ce0 type code
	 => Loading section .text @ 0x00007f55b828a0c0 type code
	 => Loading section .fini @ 0x00007f55b828dea4 type code
	 => Loading section .rodata @ 0x00007f55b828deb0 type initialized data
	 => Loading section .eh_frame_hdr @ 0x00007f55b828e154 type initialized data
	 => Loading section .eh_frame @ 0x00007f55b828e380 type initialized data
	 => Loading section .init_array @ 0x00007f55b848fd98 type initialized data
	 => Loading section .fini_array @ 0x00007f55b848fda0 type initialized data
	 => Loading section .jcr @ 0x00007f55b848fda8 type initialized data
	 => Loading section .dynamic @ 0x00007f55b848fdb0 type unknown
	 => Loading section .got @ 0x00007f55b848ffb0 type unknown
	 => Loading section .got.plt @ 0x00007f55b8490000 type initialized data
	 => Loading section .data @ 0x00007f55b8490200 type initialized data
	 => Loading section .bss @ 0x00007f55b8490270 type unitialized data
	 => Loading section .comment @ 0x0000000000000000 type unknown
	 => Loading section .shstrtab @ 0x0000000000000000 type unknown
[*] Done loading /usr/lib/libacl.so.1: 22 sections
[*] Loading image /usr/lib/libc.so.6 @ 0x00007f55b7a68000 type shared library
	 => Loading section .note.gnu.build-id @ 0x00007f55b7ee0270 type initialized data
	 => Loading section .note.ABI-tag @ 0x00007f55b7ee0294 type initialized data
	 => Loading section .dynsym @ 0x00007f55b7ee3d28 type unknown
	 => Loading section .dynstr @ 0x00007f55b7ef0d78 type unknown
	 => Loading section .rela.dyn @ 0x00007f55b7ef7b10 type relocations
	 => Loading section .rela.plt @ 0x00007f55b7eff298 type relocations
	 => Loading section .plt @ 0x00007f55b7eff3c0 type code
	 => Loading section .text @ 0x00007f55b7eff490 type code
	 => Loading section __libc_freeres_fn @ 0x00007f55b8028bc0 type code
	 => Loading section __libc_thread_freeres_fn @ 0x00007f55b80299b0 type code
	 => Loading section .rodata @ 0x00007f55b8029ba0 type initialized data
	 => Loading section .interp @ 0x00007f55b804b790 type initialized data
	 => Loading section .eh_frame_hdr @ 0x00007f55b804b7b0 type initialized data
	 => Loading section .eh_frame @ 0x00007f55b80521e0 type initialized data
	 => Loading section .gcc_except_table @ 0x00007f55b807a954 type initialized data
	 => Loading section .hash @ 0x00007f55b807ad18 type unknown
	 => Loading section .tdata @ 0x00007f55b827e718 type initialized data
	 => Loading section .tbss @ 0x00007f55b827e728 type unitialized data
	 => Loading section .init_array @ 0x00007f55b827e728 type initialized data
	 => Loading section __libc_subfreeres @ 0x00007f55b827e730 type initialized data
	 => Loading section __libc_atexit @ 0x00007f55b827e820 type initialized data
	 => Loading section __libc_thread_subfreeres @ 0x00007f55b827e828 type initialized data
	 => Loading section .data.rel.ro @ 0x00007f55b827e860 type initialized data
	 => Loading section .dynamic @ 0x00007f55b8281b80 type unknown
	 => Loading section .got @ 0x00007f55b8281d70 type unknown
	 => Loading section .got.plt @ 0x00007f55b8282000 type initialized data
	 => Loading section .data @ 0x00007f55b8282080 type initialized data
	 => Loading section .bss @ 0x00007f55b8283740 type unitialized data
	 => Loading section .comment @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.sigstack @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.sigreturn @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.siggetmask @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.tmpnam @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.tmpnam_r @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.tempnam @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.sys_errlist @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.sys_nerr @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.gets @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.getpw @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.re_max_failures @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.lchmod @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.getwd @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.sstk @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.revoke @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.mktemp @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.gtty @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.stty @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.chflags @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.fchflags @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.bdflush @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.__gets_chk @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.inet6_option_space @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.inet6_option_init @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.inet6_option_append @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.inet6_option_alloc @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.inet6_option_next @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.inet6_option_find @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.getmsg @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.putmsg @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.fattach @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.fdetach @ 0x0000000000000000 type unknown
	 => Loading section .gnu.warning.setlogin @ 0x0000000000000000 type unknown
	 => Loading section .shstrtab @ 0x0000000000000000 type unknown
	 => Loading section .symtab @ 0x0000000000000000 type unknown
	 => Loading section .strtab @ 0x0000000000000000 type unknown
[*] Done loading /usr/lib/libc.so.6: 65 sections
[*] Loading image /usr/lib/libattr.so.1 @ 0x00007f55b7c50000 type shared library
	 => Loading section .note.gnu.build-id @ 0x00007f55b7cd81c8 type initialized data
	 => Loading section .dynsym @ 0x00007f55b7cd8378 type unknown
	 => Loading section .dynstr @ 0x00007f55b7cd8930 type unknown
	 => Loading section .rela.dyn @ 0x00007f55b7cd8ce8 type relocations
	 => Loading section .rela.plt @ 0x00007f55b7cd8dc0 type relocations
	 => Loading section .init @ 0x00007f55b7cd9198 type code
	 => Loading section .plt @ 0x00007f55b7cd91c0 type code
	 => Loading section .text @ 0x00007f55b7cd9460 type code
	 => Loading section .fini @ 0x00007f55b7cdb4ac type code
	 => Loading section .rodata @ 0x00007f55b7cdb4b5 type initialized data
	 => Loading section .eh_frame_hdr @ 0x00007f55b7cdb56c type initialized data
	 => Loading section .eh_frame @ 0x00007f55b7cdb668 type initialized data
	 => Loading section .init_array @ 0x00007f55b7edbdc8 type initialized data
	 => Loading section .fini_array @ 0x00007f55b7edbdd0 type initialized data
	 => Loading section .jcr @ 0x00007f55b7edbdd8 type initialized data
	 => Loading section .dynamic @ 0x00007f55b7edbde0 type unknown
	 => Loading section .got @ 0x00007f55b7edbfd0 type unknown
	 => Loading section .got.plt @ 0x00007f55b7edc000 type initialized data
	 => Loading section .data @ 0x00007f55b7edc160 type initialized data
	 => Loading section .bss @ 0x00007f55b7edc168 type unitialized data
	 => Loading section .comment @ 0x0000000000000000 type unknown
	 => Loading section .shstrtab @ 0x0000000000000000 type unknown
[*] Done loading /usr/lib/libattr.so.1: 22 sections
PKGBUILD      plugtmp  test-kernel-security.py  yaourt-tmp-user
~/mytools $

As you can see, Intel Pin tool provides a rich API to inspect the different parts of a binary, including sections, images, functions, registers, etc, which could help security researchers to detect an anomalies such us:

  • Whether the instruction pointer points to a memory address outside the code segment?
  • Are parts of the memory getting overwritten by user input?
  • Whether there are too many RETs getting executed within a small part of the code

The post Using Intel Pin tools for binary instrumentation appeared first on Portcullis Labs.

]]>
https://labs.portcullis.co.uk/blog/using-intel-pin-tools-for-binary-instrumentation/feed/ 0
Vanilla good security practice vs. BadUSB https://labs.portcullis.co.uk/blog/vanilla-good-security-practice-vs-badusb/ https://labs.portcullis.co.uk/blog/vanilla-good-security-practice-vs-badusb/#comments Thu, 09 Oct 2014 16:18:10 +0000 https://labs.portcullis.co.uk/?p=4718 This post discusses the BadUSB research published by Karsten Nohl recently at Black Hat. You might want to check out the slides and/or video before reading on. It’s also worth noting that more recently Adam Caudill and Brandon Wilson figured out how to implement the attacks and have published proof-of-concept code which makes the challenges […]

The post Vanilla good security practice vs. BadUSB appeared first on Portcullis Labs.

]]>
This post discusses the BadUSB research published by Karsten Nohl recently at Black Hat. You might want to check out the slides and/or video before reading on.

It’s also worth noting that more recently Adam Caudill and Brandon Wilson figured out how to implement the attacks and have published proof-of-concept code which makes the challenges of defending against the original research seem somewhat more acute.

The challenges of defending against the attacks presented in the BadUSB talk largely break down into two areas:

  • Defending USB devices from tampering
  • Defending workstations and servers from bad USB devices

In this post only the latter will be discussed. However, with regard to the former, applaud the work done by Karsten Nohl. You should now be pretty wary about all your USB devices being subverted by attackers. Next time you use a keyboard or mouse that’s left lying around, you should be thinking about this research. Next time someone hands a USB stick to you, you should think if it has been reprogrammed to be a BadUSB stick. A word to our colleagues in the industry, we look forward to hearing from the USB device manufacturers about devices that can’t be tampered with in the way the researchers describe.

In the remainder of this post it has been considered how computer systems can defend or mitigate against malicious USB devices using vanilla good security practice and to what extent this is sufficient. It should be understood that this wasn’t the main crux of the research done, but as a security industry member, you should admit that it is quite interesting to consider the different USB-based attack vectors that could be used in order to gain access to computer systems as well which could be used to access a security researcher’s machine.

Defending workstations and servers from bad USB devices

If someone can plug a USB device into a workstation/laptop/server, there’s a chance that the employed USB device can subvert its normal workflow in a very clever way. The researchers Karsten Nohl and Jakob Lell presented some example attacks that were pretty innovative. Some they’ve proved work, some are just ideas for further development in this area.

The following examples can be summarised to illustrate some of the ideas outlined from their research:

  • If the USB device pretends to be a USB network interface and abuses DHCP to set a default route or a target DNS server, network traffic can be diverted to the bad guys
  • If the USB device pretends to be a keyboard it can start sending commands to a computer controlled by an attacker
  • If the USB device is left connected when the computer reboots, the computer could be attacked as it boots. The target machine may boot off it – and if the USB device is cleverly configured, the user or system administrator might not be able to detect that the device is capable of being a boot disk. Alternatively, the device might send keystrokes to modify the boot order or even modify the BIOS configuration
  • If the USB device pretends to be a USB display, it might be able to scrape what’s on a computer screen and make it available to attackers

Some of the attacks weren’t new (e.g. the Rubber Ducky has been pretending to be a keyboard for some time), but presenting these ideas together made a pretty compelling case that USB is bad.

Should we really be worried about protecting our computers from bad USB devices?

In short, yes. In some attack scenarios, these ideas really are quite worrying and and they’re pretty hard to fix or mitigate, but not in all scenarios! Some of the attacks can be mitigated fairly easily by following existing vanilla good security practice which can be found below.

Defending the boot process

Firstly we’ll examine how to protect the boot process against malicious USB devices using vanilla good security practice.

  • Configure the BIOS of computers to only boot from the internal hard disk

This should stop attackers booting off USB devices. But the bad USB device might reconfigure your BIOS to boot off some other device – specifically if it sends keystrokes during system boot.

  • Set a BIOS password to prevent modification of BIOS settings

This should make it pretty hard for anyone to boot off a USB device whether or not they are using a bad USB device. So, in short I don’t think it’s necessary to worry about your users being tricked into booting off malicious devices in this context. It’s fairly simple to secure the boot process against the attack scenario described.

Defending servers

Clearly servers are key assets and physical security controls probably provide a good level of protection already. In my experience, server rooms are access controlled – so relatively few people are allowed in and those who are have their identities checked, an access log is maintained and they might even be vetted to a certain extent first. Once they’re in, their access is (sometimes at least) restricted to only the racks they need to work in. The racks prevent the poking of usb devices into other people’s servers. However, everything in the exposed racks is certainly vulnerable to potential USB attacks.

Pragmatically, if the attacker has physical access to your server, you probably have bigger problems than a USB-based attack.

  • How to protect against bad USB devices that pretend to be keyboards?

Lock your laptop/workstation when it’s not in use. Then all the fake keyboard can do is try to log in. If the the bad keyboard doesn’t know your password, you’re reasonably safe. It could conceivably lock out your account or other AD users, but that’s not an awfully compelling attack.

  • How to protect laptops when they’re not being used?

Use a full disk encryption solution and make sure that laptops are powered down when not in use. This will make sure that a password is required to boot/resume the OS. Some of the USB attacks discussed are effective even with the host booted and the screen locked. Specifically the USB network device intercepting your traffic. Full disk encryption (FDE) is pretty essential anyway for laptops in most companies. To get the full benefit from FDE, hosts should be powered down when not in use, so this lines up with our requirement of keeping hosts protected from USB attacks by not leaving hosts unnecessarily booted and therefore exposed to attack.

  • How to protect workstations from fake keyboards?

Locking down the desktop environment

This is fairly difficult to do well, but good security practice can help to mitigate. Using lockdown technologies like group policy, SRP, app locker and kiosk software, devices can be restricted to only run the application they need to run. Clearly this is appropriate in some environments, but not in others. Corporate workstations can be and sometimes are locked down – you can’t run any old program, you can’t browse the C:\ drive, you can’t Start|Run or WindowsKey+R.

How does this help? Well, the bad keyboard is probably going to send a series of keystrokes in order to download and run some malware. If a user’s login session has been restricted, the bad keyboard’s attempt to use Windows-key+R or launch IE may not work at all.

  • Anti-Virus, Content Checkers

…and if the attacker’s going to be downloading malware, using a content checker for web traffic and having AV installed might (and I stress might) save the day.

  • USB Lockdown

This will be an interesting area to watch. Will there be a rush to buy third party software to block certain types / classes of USB device? Some vendors are claiming to protect against BadUSB attacks (but I haven’t tested their software, so am not linking to them from this post). Google for terms like “usb endpoint device control”, “usb endpoint protection” and possibly adding the term “badusb” should lead you towards what the market’s currently offering.

The idea of some sort of USB Firewall is an attractive one, particularly one that ships as part of the OS. It remains to be seen how well this could be implemented, how easily it could be bypassed and to what extent is impairs business operations.

As a closing thought, if you haven’t considered the perils of uncontrolled access to Firewire ports and PCI Express slots, maybe worry about those first.

Mitigations

Windows

Windows can help to mitigate this issue by using GPO as IronGeek described in the following post Plug and Pray Malicious USB devices

GNU/Linux: udev rules

The BadUSB attack bases itself on the fact that computers allow and enable HID devices on all usb ports. On Linux, a temporarily fix could be employed using udev to temporarily disable the addition of new HID devices as described on StackExchange by user10008 . For preparation, create a file /etc/udev/rules.d/10-usbblock.rules with the content:

    #ACTION=="add", ATTR{bInterfaceClass}=="03" RUN+="/bin/sh -c 'echo 0 >/sys$DEVPATH/../authorized'"

To block other classes, It is needed to look up the class number and substitute copy the line, and change the class. To block all new HID devices the following command can be employed:

    sed -i 's/#//' /etc/udev/rules.d/10-usbblock.rules; udevadm control --reload-rules

To unblock all new HID devices the following command can be employed:

    sed -i 's/^/#/' /etc/udev/rules.d/10-usbblock.rules; udevadm control --reload-rules

Note that before powering off the system, It is required to remove the block as udev’s setting are persistent, and thusly legitimate HID devices would be rejected on boot.

FreeBSD

The people from FreeBSD already submitted a patch to remediate this issue. The patch files can be examined at FreeBSD SVN web. This patch adds some system tunables that can be controlled by the well known sysctl.

hw.usb.disable_enumeration: 0
dev.uhub.0.disable_enumeration: 0
dev.uhub.1.disable_enumeration: 0
[...]

It should be noted that these system tunables can be also set through /boot/loader.conf

Conclusion

So with these potential mitigations in mind, let’s restate the attacks above and review how concerned we should be:

It could pretend to be a USB network interface and abuse DHCP to set your default route or your DNS server. Either way, you could end up with network traffic being diverted to the bad guys.

I am pretty worried about this attack. But it only works when my computer is booted. It even works when my screen is locked. The attacker obviously requires physical access, but that’s entirely possible in a corporate environment.

If the USB device pretends to be a keyboard it can start sending commands to your computer – as if you typed them.

This one is worth bearing in mind. It’s possible to mitigate to an extent if you prevent users from running unnecessary programs. It remains possible that your bad USB device might suddenly become a keyboard when you’re least expecting it.

Limiting the amount of time your USB device is connected narrows the attack window. But that doesn’t really fix the problem. Your keyboard and mouse are plugged in all the time, right? And are you sure they haven’t been tampered with?

If the USB device is left connected when the computer reboots, you computer could be attacked as it boots. The computer may boot off it – and if the USB device is cleverly configured, you might not be able to tell the device is capable of being a boot disk. Alternatively, the device might send keystrokes to modify the boot order or even modify the BIOS.

I’m not worried about this really. It’s possible to secure the boot process against these attacks.

If the USB device pretends to be a USB display, it might be able to scrape what’s on your screen and make it available to the bad guys.

I’m fairly worried about this one. Obviously my screen can’t be locked for this attack – if it were the attacker doesn’t really win by screenshotting the log in screen. However, if my screen is unlocked – maybe someone passes me a USB stick, this could really work.

The post Vanilla good security practice vs. BadUSB appeared first on Portcullis Labs.

]]>
https://labs.portcullis.co.uk/blog/vanilla-good-security-practice-vs-badusb/feed/ 0
An introduction to binary dynamic analysis https://labs.portcullis.co.uk/blog/an-introduction-to-binary-dynamic-analysis/ https://labs.portcullis.co.uk/blog/an-introduction-to-binary-dynamic-analysis/#comments Tue, 13 May 2014 13:29:24 +0000 https://labs.portcullis.co.uk/?p=3001 The term dynamic instrumentation refers to the act of monitoring the execution of a program in order to extract debug information, to measure code performance or to detect errors. Dynamic instrumentation can be used to generate measures of functions properties such as execution time, call counts, registers status or call graphs. Tools Several software solutions […]

The post An introduction to binary dynamic analysis appeared first on Portcullis Labs.

]]>
The term dynamic instrumentation refers to the act of monitoring the execution of a program in order to extract debug information, to measure code performance or to detect errors. Dynamic instrumentation can be used to generate measures of functions properties such as execution time, call counts, registers status or call graphs.

Tools

Several software solutions exists to help the developers and researchers to commit this task of inspecting a program runtime behaviour, being some of the prominent the following ones:

Two of the the most widely used tool dynamic binary instrumentation tools are PIN and DynamoRIO. PIN is developed by Intel and provided by the University of Virginia whereas DynamoRIO is a collaboration between Hewlett-Packard and MIT. Both are free to use but only DynamoRIO is open source. PIN and DynamoRIO are both equally useful and usually the election is the result of personal taste.

mtrace

mtrace is the memory debugger included in the GNU C Library. The usage of mtrace(3) can be summarised as follows:

  1. Export the variable MALLOC_TRACE to point to the result logfile
  2. Include the header mcheck.h in the code
  3. Call to mtrace() before allocating memory
  4. Call untrace() at the end of the code (usually the main() function)
  5. Compile the program with debugging symbols (gcc prog.c -g)
  6. Read output using mtrace exec_file mtrace_output filename

Following a example extracted from the mtrace(3) man page to clarify the usage:

#include <mcheck.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
   int j;

   mtrace();

   for (j = 0; j < 2; j++)
       malloc(100);            /* Never freed--a memory leak */

   calloc(16, 16);             /* Never freed--a memory leak */
   exit(EXIT_SUCCESS);
}

A little script could be created in order to automate the compilation the analysis:

#!/bin/sh
export MALLOC_TRACE=mtrace.log
bin=prog
src=mtrace.c
gcc -g $src -o $bin
./$bin
mtrace $bin $MALLOC_TRACE

The execution will result in the following excerpt:

$ ./mtrace.sh 

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000002054460     0x64  at /home/user/mtrace.c:11 (discriminator 2)
0x00000000020544d0     0x64  at /home/user/mtrace.c:11 (discriminator 2)
0x0000000002054540    0x100  at /home/user/mtrace.c:15

As can be seen, mtrace(3) has detected the error absence of free(), resulting in a memory leak error.

Intel PIN tool

PIN is a framework for creating dynamic binary analysis tools for the i386 and x86-64 architectures that can be used to perform program analysis on user space applications in Linux and Windows at run time on the compiled binary files. Pin provides an API that abstracts the instruction set and the binary schema and allows to inspect register contents, program code and symbol and debug information.

PIN performs instrumentation by taking control of the program just after it loads into memory and recompiling just-in-time sections of binary code just before they are run. Regarding the performance, PIN’s overhead is about 30 percent.PIN was originally created as a tool for computer architecture analysis, but its flexible API and an active community (called "Pinheads") have created a diverse set of tools for security, emulation and parallel program analysis.

A pin tool comprises of three types of routines:

  1. Instrumentation routines that enable the insertion of analysis routines
  2. Analysis routines which are called when the code they are associated is run
  3. Callback routines that called when specific conditions are met or when a certain event has occurred such as library loads, system calls, signals/exceptions and thread creation events

PIN includes in the directories source/tools/ManualExamples and source/tools/SimpleExamples several examples. Below can be seen the execution of the instruction counter and opcode mix profiler PIN tools:

$ cd pin-2.12-58423-gcc.4.4.7-linux
$ ./pin -appdebug -t source/tools/ManualExamples/obj-ia32/inscount0.so -- `which evolution`
$ cd pin-2.12-58423-gcc.4.4.7-linux
$ ./pin -t source/tools/SimpleExamples/obj-intel64/opcodemix.so -- /bin/ls

Another interesting example can be found on the imageload.cpp file. This example demonstrates the use of the API functions IMG_AddInstrumentFunction and IMG_AddUnloadFunction which are called when the binary images are loaded by the operating system:

$ cd source/tools/ManualExamples
$ make -f makefile obj-intel64/imageload.so
$ ../../../pin -t obj-intel64/imageload.so -- /bin/ls
$ cat imageload.out
	Loading /bin/ls, Image id = 1
	Loading /lib64/ld-linux-x86-64.so.2, Image id = 2
	Loading /lib/x86_64-linux-gnu/libselinux.so.1, Image id = 3
	Loading /lib/x86_64-linux-gnu/librt.so.1, Image id = 4
	Loading /lib/x86_64-linux-gnu/libacl.so.1, Image id = 5
	Loading /lib/x86_64-linux-gnu/libc.so.6, Image id = 6
	Loading /lib/x86_64-linux-gnu/libdl.so.2, Image id = 7
	Loading /lib/x86_64-linux-gnu/libpthread.so.0, Image id = 8
	Loading /lib/x86_64-linux-gnu/libattr.so.1, Image id = 9
	Unloading /bin/ls
	Unloading /lib64/ld-linux-x86-64.so.2
	Unloading /lib/x86_64-linux-gnu/libselinux.so.1
	Unloading /lib/x86_64-linux-gnu/librt.so.1
	Unloading /lib/x86_64-linux-gnu/libacl.so.1
	Unloading /lib/x86_64-linux-gnu/libc.so.6
	Unloading /lib/x86_64-linux-gnu/libdl.so.2
	Unloading /lib/x86_64-linux-gnu/libpthread.so.0
	Unloading /lib/x86_64-linux-gnu/libattr.so.1	

A classification of some of the shipped PIN tools examples are:

Analysing instructions

  • inscount0.cpp: checks number of executed instructions of application program
  • itrace.cpp: lists addresses of executed instructions of application program
  • pinatrace.cpp: lists addresses of accessed memory and type of operation (read, write)
  • opcodemix.cpp: lists opcodes of executed instructions with number of executions and category summary
  • regmix.cpp: analyses the usage or program registers

Analysing basic blocks

  • inscount1.cpp: counts all instructions of a basic block at once.
  • edgcnt.cpp:lists addresses of jump instructions, type of jump (direct, indirect), and number of times performed

Analysing routines

  • proccount.cpp: counts number of times each routine is invoked and number of instructions in it

Analysing libraries

  • imageload.cpp: lists loading and unloading of dynamic libraries invoked by program

Developing the first PIN tool

PIN includes in source/tools/MyPinTool/ a sample tool that can be used as code code base to start creating basic PIN tools. To create, compile and execute a this basic example, the following commands could be used:

$ cp -r pin-2.12-58423-gcc.4.4.7-linux/source/tools/MyPinTool/ pin1/
$ cd pin1
$ make -f makefile mPIN_ROOT=../pin-2.12-58423-gcc.4.4.7-linux
$ ls obj-intel64/
MyPinTool.o  MyPinTool.so
$ ../pin-2.12-58423-gcc.4.4.7-linux/pin -t obj-intel64/MyPinTool.so -- /bin/ls
===============================================
This application is instrumented by MyPinTool
===============================================
makefile  makefile.rules  MyPinTool.cpp  obj-intel64

To make things simple, a development directory “mytools” could be created outside the PIN directory hierarchy:

$ ls -l
total 35636
drwxr-xr-x 4 user users     4096 mar  9 22:39 mytools
lrwxrwxrwx 1 user users       30 ago 24  2013 pin -> pin-2.12-58423-gcc.4.4.7-linux
drwxr-xr-x 7 user users     4096 mar 10 01:12 pin-2.12-58423-gcc.4.4.7-linux

The development directory will contain the tools source code and the objects:

 
$ ls -l mytools
total 120
-rw-r--r-- 1 user users  676 feb  3 2013 Makefile
-rwxr-xr-x 1 user users  366 feb  3 2013 build.sh
-rw-r--r-- 1 user users 6033 feb  9 05:08 check_pc_sections.cpp
-rw-r--r-- 1 user users 7062 feb  9 03:27 check_secciones.cpp
-rw-r--r-- 1 user users 7796 feb  9 04:44 detect_pc_noexec.cpp
-rw-r--r-- 1 user users 5278 feb  9 02:30 load_unload_imag.cpp
-rw-r--r-- 1 user users 5435 feb  9 02:44 load_unload_sec.cpp
-rw-r--r-- 1 user users 2822 feb  4  2013 makefile.rules
drwxr-xr-x 2 user users 4096 feb  3 18:46 obj-intel64

A script (build.sh) could be created in order to help the compilation of PIN tools that reside in the development directory. The code of the script could be as shown below:

#!/bin/sh
PIN_ROOT=../pin
dstdir=obj-intel64
function negrita() { echo -e &quot;\033[1m${1}\033[0m&quot;; }

test -d $dstdir || mkdir $dstdir

for f in *.cpp; do
    negrita &quot;[*] Building $f&quot;;
    obj=`echo $f | sed -e 's/cpp/so/'`
    make $dstdir/$obj PIN_ROOT=$PIN_ROOT
    negrita &quot;[*] Exec $PIN_ROOT/pin -t $dstdir/$obj -- <program>&quot;
done

This script can be used to compile or all tools contained in the “mytools” development directory at one. Also, some tricks could help when using this dynamic instrumentation framework:

  • The option -appdebug tells PIN to start a GDB server to debug the application
  • The -appdebug option can also be used to debug from IDA Pro any application using PIN using the remote GDB debugger
  • It can’t be specified which port PIN will listen in as it will be randomly selected every time we execute PIN
    • The post An introduction to binary dynamic analysis appeared first on Portcullis Labs.

      ]]> https://labs.portcullis.co.uk/blog/an-introduction-to-binary-dynamic-analysis/feed/ 0 Checking RDP support across an internal network https://labs.portcullis.co.uk/blog/checking-rdp-across-an-internal-network/ https://labs.portcullis.co.uk/blog/checking-rdp-across-an-internal-network/#comments Mon, 10 Feb 2014 06:32:00 +0000 https://labs.portcullis.co.uk/?p=3051 We’ve recently added some new features to rdp-sec-check, which is a Perl script to enumerate security settings of an RDP Service (AKA Terminal Services). The tool download is available in the rdp-sec-check page. The following new features were added to rdp-sec-check: Support for targets file Support for saving the tool output to a specified logfile […]

      The post Checking RDP support across an internal network appeared first on Portcullis Labs.

      ]]>
      We’ve recently added some new features to rdp-sec-check, which is a Perl script to enumerate security settings of an RDP Service (AKA Terminal Services). The tool download is available in the rdp-sec-check page.

      The following new features were added to rdp-sec-check:

      • Support for targets file
      • Support for saving the tool output to a specified logfile
      • Control over the connection and responses timeouts
      • Control over the number of retries when timeouts occurs

      rdp-sec-check command line help

      $ rdp-sec-check.pl
      Starting rdp-sec-check v0.9-beta ( https://labs.portcullis.co.uk/application/rdp-sec-check/ )
      Copyright (C) 2014 Mark Lowe (mrl@portcullis-security.com)
      
      /usr/local/bin/rdp-sec-check.pl [ options ]  ( --file hosts.txt | host | host:port )
      
      options are:
      
        --file hosts.txt	targets, one ip:port per line
        --outfile out.log	output logfile
        --timeout sec		receive timeout (default 10s)
        --retries times	number of retries after timeout
        --verbose
        --debug
        --help
      
      Example:
               /usr/local/bin/rdp-sec-check.pl 192.168.1.1
               /usr/local/bin/rdp-sec-check.pl --file hosts.txt --timeout 15 --retries 3
               /usr/local/bin/rdp-sec-check.pl --outfile rdp.log 192.168.69.69:3389
               /usr/local/bin/rdp-sec-check.pl --file hosts.txt --outfile rdp.log --verbose
      
      

      Example output: A single Windows 2003 R2 RDP service scan

      The following is an example of a single machine scan using 3 seconds as timeout for connections and responses and output saving using the file named out.log:

      $ ./rdp-sec-check.pl --outfile out.log --timeout 3 192.168.13.13
      Starting rdp-sec-check v0.9-beta ( https://labs.portcullis.co.uk/application/rdp-sec-check/ ) at Thu Jan 23 12:16:26 2014
      
      [+] Scanning 1 hosts
      
      Target:    192.168.13.13
      IP:        192.168.13.13
      Port:      3389
      
      [+] Checking supported protocols
      
      [-] Checking if RDP Security (PROTOCOL_RDP) is supported...Supported
      [-] Checking if TLS Security (PROTOCOL_SSL) is supported...Not supported - SSL_CERT_NOT_ON_SERVER
      [-] Checking if CredSSP Security (PROTOCOL_HYBRID) is supported [uses NLA]...Not supported - SSL_CERT_NOT_ON_SERVER
      
      [+] Checking RDP Security Layer
      
      [-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_NONE...Not supported
      [-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_40BIT...Supported.  Server encryption level: ENCRYPTION_LEVEL_CLIENT_COMPATIBLE
      [-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_128BIT...Supported.  Server encryption level: ENCRYPTION_LEVEL_CLIENT_COMPATIBLE
      [-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_56BIT...Supported.  Server encryption level: ENCRYPTION_LEVEL_CLIENT_COMPATIBLE
      [-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_FIPS...Supported.  Server encryption level: ENCRYPTION_LEVEL_CLIENT_COMPATIBLE
      
      [+] Summary of protocol support
      
      [-] 192.168.13.13:3389 supports PROTOCOL_RDP   : TRUE
      [-] 192.168.13.13:3389 supports PROTOCOL_SSL   : FALSE
      [-] 192.168.13.13:3389 supports PROTOCOL_HYBRID: FALSE
      
      [+] Summary of RDP encryption support
      
      [-] 192.168.13.13:3389 has encryption level: ENCRYPTION_LEVEL_CLIENT_COMPATIBLE
      [-] 192.168.13.13:3389 supports ENCRYPTION_METHOD_NONE   : FALSE
      [-] 192.168.13.13:3389 supports ENCRYPTION_METHOD_40BIT  : TRUE
      [-] 192.168.13.13:3389 supports ENCRYPTION_METHOD_128BIT : TRUE
      [-] 192.168.13.13:3389 supports ENCRYPTION_METHOD_56BIT  : TRUE
      [-] 192.168.13.13:3389 supports ENCRYPTION_METHOD_FIPS   : TRUE
      
      [+] Summary of security issues
      
      [-] 192.168.13.13:3389 has issue FIPS_SUPPORTED_BUT_NOT_MANDATED
      [-] 192.168.13.13:3389 has issue WEAK_RDP_ENCRYPTION_SUPPORTED
      [-] 192.168.13.13:3389 has issue ONLY_RDP_SUPPORTED_MITM
      [-] 192.168.13.13:3389 has issue NLA_NOT_SUPPORTED_DOS
      
      rdp-sec-check v0.9-beta completed at Thu Jan 23 12:16:27 2014
      

      Example: A fast network scan using timeouts and retries

      In this example, a targets file to test the network 172.18.19.0/24 is generated using a shell one liner:

      $ for i in $(seq 1 254); do echo 172.18.19.$i; done >> targets.txt
      

      Then rdp-sec-check is fed with the targets file targets.txt and a 3 second limit is set on the connections and responses; if the connections times out, rdp-sec-check will retry 2 times before exiting. Finally, the scan log will be saved in the file out.log.

      $ ./rdp-sec-check.pl --file targets.txt --outfile out.log --timeout 3 --retries 2
      

      In this example, the timeout and retries parameters are set for a fast local network scan. When scanning machines through the Internet or VPN, the timeout should be set to a higher value. Also, depending on the stability of the targets and/or the pentester’s Internet connection, the value of the parameter retries should be tuned.

      Example: A Internet network scan using timeouts and retries

      In this example, I have configured rdp-sec-check with a targets file named targets.txt and a 15 seconds time limit on the connections and responses (with a fault tolerance of 5). Again, all the output will be saved in the file named out.log. This parameter settings should help rdp-sec-check to succeed where the network connectivity is unreliable:

      $ ./rdp-sec-check.pl --file targets.txt --outfile out.log --timeout 15 --retries 5
      

      The post Checking RDP support across an internal network appeared first on Portcullis Labs.

      ]]>
      https://labs.portcullis.co.uk/blog/checking-rdp-across-an-internal-network/feed/ 0
      OHM 2013: Review of “Returning signals for fun and profit” https://labs.portcullis.co.uk/blog/ohm-2013-review-of-returning-signals-for-fun-and-profit/ https://labs.portcullis.co.uk/blog/ohm-2013-review-of-returning-signals-for-fun-and-profit/#comments Tue, 05 Nov 2013 14:38:10 +0000 https://labs.portcullis.co.uk/?p=1458 One interesting talk I’ve attended on OHM 2013 was titled “Returning Signals for fun and profit”. This talk was given by Erik Bosman. The talk refers to a new way exploiting binaries using the Linux signal’s stack frame. This post could be summarised with the following words: Return oriented programming has been proven to be […]

      The post OHM 2013: Review of “Returning signals for fun and profit” appeared first on Portcullis Labs.

      ]]>
      One interesting talk I’ve attended on OHM 2013 was titled “Returning Signals for fun and profit”. This talk was given by Erik Bosman. The talk refers to a new way exploiting binaries using the Linux signal’s stack frame.

      This post could be summarised with the following words:

      Return oriented programming has been proven to be a very effective way of circumventing data execution prevention features like ASLR present in modern operating systems, but the attacker needs to know the binary structure of the target executable in order to extract the so-called borrowed chunks of code. Here a generic binary exploitation technique will be covered which in some cases requires no knowledge about the running program.

      Contexts and switches

      A clever way to alter the control flow of the program by using context control will be described. A program execution context comprises the CPU’s registers, the program counter plus other operating system specific data at any point in time. A context switch is the process of storing and restoring the state of a process so that execution can be resumed from the same point at a later time. There are two types of context switches: software and hardware.

      In this post I will cover the software context switch used in the process of a task returning from a software signal on 64bits. The Linux implementation of signals is fully POSIX-compliant, and the data used to recover the task from a previus state (the interrupted context: registers, program counter, signal mask, etc.) is be saved in a ucontext_t structure on the stack for the thread, along with the trampoline return address. Signal handlers installed with the SA_SIGINFO flag are able to examine this ucontext_t structure. The definition of the structure ucontext can be seen in the include/uapi/asm-generic/ucontext.h header file:

      #ifndef __ASM_GENERIC_UCONTEXT_H
      #define __ASM_GENERIC_UCONTEXT_H
      
      struct ucontext {
              unsigned long     uc_flags;
              struct ucontext  *uc_link;
              stack_t           uc_stack;
              struct sigcontext uc_mcontext;
              sigset_t          uc_sigmask;   /* mask last for extensibility */
      };
      
      #endif /* __ASM_GENERIC_UCONTEXT_H */
      

      The structure sigcontext, which holds the saved state of the task (registers, etc) can be examined in the arch/x86/include/asm/sigcontext.h header file:

      struct sigcontext {
              unsigned long r8;
              unsigned long r9;
              unsigned long r10;
              unsigned long r11;
              unsigned long r12;
              unsigned long r13;
              unsigned long r14;
              unsigned long r15;
              unsigned long di;
              unsigned long si;
              unsigned long bp;
              unsigned long bx;
              unsigned long dx;
              unsigned long ax;
              unsigned long cx;
              unsigned long sp;
              unsigned long ip;
              unsigned long flags;
              unsigned short cs;
              unsigned short gs;
              unsigned short fs;
              unsigned short __pad0;
              unsigned long err;
              unsigned long trapno;
              unsigned long oldmask;
              unsigned long cr2;
      
              /*
               * fpstate is really (struct _fpstate *) or (struct _xstate *)
               * depending on the FP_XSTATE_MAGIC1 encoded in the SW reserved
               * bytes of (struct _fpstate) and FP_XSTATE_MAGIC2 present at the end
               * of extended memory layout. See comments at the definition of
               * (struct _fpx_sw_bytes)
               */
              void __user *fpstate;           /* zero when no FPU/extended context */
              unsigned long reserved1[8];
      };
      

      The struct _fpstate __user *fpstate is defined in the arch/x86/include/uapi/asm/sigcontext.h header file:

      struct _fpstate {
              /* Regular FPU environment */
              unsigned long   cw;
              unsigned long   sw;
              unsigned long   tag;
              unsigned long   ipoff;
              unsigned long   cssel;
              unsigned long   dataoff;
              unsigned long   datasel;
              struct _fpreg   _st[8];
              unsigned short  status;
              unsigned short  magic;          /* 0xffff = regular FPU data only */
      
              /* FXSR FPU environment */
              unsigned long   _fxsr_env[6];   /* FXSR FPU env is ignored */
              unsigned long   mxcsr;
              unsigned long   reserved;
              struct _fpxreg  _fxsr_st[8];    /* FXSR FPU reg data is ignored */
              struct _xmmreg  _xmm[8];
              unsigned long   padding1[44];
      
              union {
                      unsigned long   padding2[12];
                      struct _fpx_sw_bytes sw_reserved; /* represents the extended
                                                         * state info */
              };
      };
      

      Finally, the signal information structure struct siginfo is available in include/uapi/asm-generic/siginfo.h:

      From include/uapi/asm-generic/siginfo.h:

      typedef struct siginfo {
              int si_signo;
              int si_errno;
              int si_code;
      
              union {
                      int _pad[SI_PAD_SIZE];
      
                      /* kill() */
                      struct {
                              __kernel_pid_t _pid;    /* sender's pid */
                              __ARCH_SI_UID_T _uid;   /* sender's uid */
                      } _kill;
      
                      /* POSIX.1b timers */
                      struct {
                              __kernel_timer_t _tid;  /* timer id */
                              int _overrun;           /* overrun count */
                              char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
                              sigval_t _sigval;       /* same as below */
                              int _sys_private;       /* not to be passed to user */
                      } _timer;
      
                      /* POSIX.1b signals */
                      struct {
                              __kernel_pid_t _pid;    /* sender's pid */
                              __ARCH_SI_UID_T _uid;   /* sender's uid */
                              sigval_t _sigval;
                      } _rt;
      
                      /* SIGCHLD */
                      struct {
                              __kernel_pid_t _pid;    /* which child */
                              __ARCH_SI_UID_T _uid;   /* sender's uid */
                              int _status;            /* exit code */
                              __ARCH_SI_CLOCK_T _utime;
                              __ARCH_SI_CLOCK_T _stime;
                      } _sigchld;
      
                      /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
                      struct {
                              void __user *_addr; /* faulting insn/memory ref. */
      #ifdef __ARCH_SI_TRAPNO
                              int _trapno;    /* TRAP # which caused the signal */
      #endif
                              short _addr_lsb; /* LSB of the reported address */
                      } _sigfault;
      
                      /* SIGPOLL */
                      struct {
                              __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
                              int _fd;
                      } _sigpoll;
      
                      /* SIGSYS */
                      struct {
                              void __user *_call_addr; /* calling user insn */
                              int _syscall;   /* triggering system call number */
                              unsigned int _arch;     /* AUDIT_ARCH_* of syscall */
                      } _sigsys;
              } _sifields;
      } __ARCH_SI_ATTRIBUTES siginfo_t;
      

      As a summary, the the following kernel source files play a part in this technique:

      arch/x86/include/uapi/asm/sigcontext32.h (32bits)
         	struct _fpstate_ia32
         	struct sigcontext_ia32
      arch/x86/include/uapi/asm/sigcontext.h
         	struct _fpstate
      	#ifndef __KERNEL__
         	 	struct sigcontext (contains void __user *fpstate; )
      	#endif /* !__KERNEL__ */
      arch/x86/include/asm/sigcontext.h
       	#include &lt;uapi/asm/sigcontext.h&gt;
         	struct sigcontext ( contains void __user *fpstate; )</pre>
      

      The good thing about storing this data on the stack is that the kernel does not need to remember the signals it delivered, but the bad point is that It can be forged.

      When switching context, the kernel will execute setup_rt_frame, where all user-space registers are saved and the kernel stack frame return address is modified to point to the handler of the installed signal handler. A small sequence of code jumper is put on the user stack which will return us to kernel space once the signal handler has finished.

      From arch/x86/kernel/signal.c:

      static int
      setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                      struct pt_regs *regs)
      {
              int usig = signr_convert(sig);
              sigset_t *set = sigmask_to_save();
              compat_sigset_t *cset = (compat_sigset_t *) set;
      
              /* Set up the stack frame */
              if (is_ia32_frame()) {
                      if (ka->sa.sa_flags & SA_SIGINFO)
                              return ia32_setup_rt_frame(usig, ka, info, cset, regs);
                      else
                              return ia32_setup_frame(usig, ka, cset, regs);
              } else if (is_x32_frame()) {
                      return x32_setup_rt_frame(usig, ka, info, cset, regs);
              } else {
                      return __setup_rt_frame(sig, ka, info, set, regs);
              }
      }
      

      From arch/x86/kernel/signal.c:

      static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                                  sigset_t *set, struct pt_regs *regs)
      {
              struct rt_sigframe __user *frame;
              void __user *fp = NULL;
              int err = 0;
      
              frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe), &fp);
      
              if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                      return -EFAULT;
      
              if (ka->sa.sa_flags & SA_SIGINFO) {
                      if (copy_siginfo_to_user(&frame->info, info))
                              return -EFAULT;
              }
      
              put_user_try {
                      /* Create the ucontext.  */
                      if (cpu_has_xsave)
                              put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
                      else
                              put_user_ex(0, &frame->uc.uc_flags);
                      put_user_ex(0, &frame->uc.uc_link);
                      err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
      
                      /* Set up to return from userspace.  If provided, use a stub
                         already in userspace.  */
                      /* x86-64 should always use SA_RESTORER. */
                      if (ka->sa.sa_flags & SA_RESTORER) {
                              put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
                      } else {
                              /* could use a vstub here */
                              err |= -EFAULT;
                      }
              } put_user_catch(err);
      
              err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
              err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
      
              if (err)
                      return -EFAULT;
      
              /* Set up registers for signal handler */
              regs->di = sig;
              /* In case the signal handler was declared without prototypes */
              regs->ax = 0;
      
              /* This also works for non SA_SIGINFO handlers because they expect the
                 next argument after the signal number on the stack. */
              regs->si = (unsigned long)&frame->info;
              regs->dx = (unsigned long)&frame->uc;
              regs->ip = (unsigned long) ka->sa.sa_handler;
      
              regs->sp = (unsigned long)frame;
      
              /* Set up the CS register to run signal handlers in 64-bit mode,
                 even if the handler happens to be interrupting 32-bit code. */
              regs->cs = __USER_CS;
      
              return 0;
      }
      

      The above code restores the exact user-register contents into the kernel stack frame (including the return address and flags register) and executes a normal return from syscall, bringing the execution flow back to the original code that jumped to the signal handler.

      The stack frame image that Linux configures for signal returning assembles the following diagram:

       [-------------]
       [    STACK    ]
       [-------------]
       [   FPSTATE   ]
       [-------------]
       [   UCONTEXT  ]
       [-------------]
       [ SIGINFO+arg ]
       [-------------]
      

      A detailed view on 64bits should assemble the following diagram:

           [------------------------------------------]
      0x00 [  rt_sigreturn()      |  uc_flags         ]
      0x10 [  &uc                 |  uc_stack.ss_sp   ]
      0x20 [  uc_stack.ss_flags   |  uc_stack.ss_size ]
      0x30 [  r8                  |  r9               ]
      0x40 [  r10                 |  r11              ]
      0x50 [  r12                 |  r13              ]
      0x60 [  r14                 |  r15              ]
      0x70 [  rdi                 |  rsi              ]
      0x80 [  rbp                 |  rbx              ]
      0x90 [  rdx                 |  rax              ]
      0xA0 [  rcx                 |  rsp              ]
      0xB0 [  rip                 |  eflags           ]
      0xC0 [  cs / gs / fs        |  err              ]
      0xD0 [  trapno              |  oldmask (unused) ]
      0xE0 [  cr2 (segfault addr) |  &fpstate         ]
      0xF0 [  __reserved          |  sigmask          ]
           [------------------------------------------]
      

      Exploitation

      By forging the contents of the struct sigcontext, which holds the saved registers values, setting the $rax register to the desired syscall number, setting the systemcall args properly and finally setting the program counter $rip pointing to an >syscall; ret gadget, we can effectively modify the execution flow of the program and execute the desired systemcall. Also, several SigRet frames can be chained by using the value of the saved $rsp register of the returning frame and the gadget syscall;ret.

      • rax => syscall_number
      • rdi => arg1
      • rsi => arg2
      • rdx => arg3
      • r10 => arg4
      • r8 => arg5
      • r9 => arg6
      • rip => syscall;ret
      • rsp => next_frame
      • cs=0×33 / gs=0×0 / fs=0×0
      • &fpstate = NULL

      The forged stack structure should assemble the following:

           [------------------------------------------]
      0x00 [  rt_sigreturn()      |  uc_flags         ]*
      0x10 [  &uc                 |  uc_stack.ss_sp   ]
      0x20 [  uc_stack.ss_flags   |  uc_stack.ss_size ]
      0x30 [  arg5                |  arg6             ]*
      0x40 [  arg4                |  r11              ]*
      0x50 [  r12                 |  r13              ]
      0x60 [  r14                 |  r15              ]
      0x70 [  arg1                |  arg2             ]*
      0x80 [  rbp                 |  rbx              ]
      0x90 [  arg3                |  syscall_number   ]*
      0xA0 [  rcx                 |  next_frame       ]*
      0xB0 [  syscall;ret         |  eflags           ]*
      0xC0 [  cs=0x33/gs=0/fs=0   |  err              ]*
      0xD0 [  trapno              |  oldmask (unused) ]
      0xE0 [  cr2 (segfault addr) |  &fpstate         ]*
      0xF0 [  __reserved          |  sigmask          ]
           [------------------------------------------]
      

      As a summary, for SigReturn oriented programming, the following requirements are needed:

      1. Controllable stack
      2. Knowing the address of a system call gadget
      3. A known writable address
      4. Known file descriptor
      5. Control over the RAX register

      More information:

      The post OHM 2013: Review of “Returning signals for fun and profit” appeared first on Portcullis Labs.

      ]]>
      https://labs.portcullis.co.uk/blog/ohm-2013-review-of-returning-signals-for-fun-and-profit/feed/ 0