Skip to content

Instantly share code, notes, and snippets.

@Eterna1
Last active July 18, 2018 23:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Eterna1/245e3ae52ca78c0b51ff28e3e0b90ffd to your computer and use it in GitHub Desktop.
Save Eterna1/245e3ae52ca78c0b51ff28e3e0b90ffd to your computer and use it in GitHub Desktop.
UE tutorial

Cheatsheet

from unicorn import * - ładujemy bibliotekę unicorna i stałe
from unicorn.x86_const import * - ładujemy stałe dotyczące architektur x86 i x86_64

stałe występujące w module unicorn:

UC_API_MAJOR                UC_ERR_VERSION              UC_MEM_READ                 UC_PROT_ALL
UC_API_MINOR                UC_ERR_WRITE_PROT           UC_MEM_READ_AFTER           UC_PROT_EXEC
UC_ARCH_ARM                 UC_ERR_WRITE_UNALIGNED      UC_MEM_READ_PROT            UC_PROT_NONE
UC_ARCH_ARM64               UC_ERR_WRITE_UNMAPPED       UC_MEM_READ_UNMAPPED        UC_PROT_READ
UC_ARCH_M68K                UC_HOOK_BLOCK               UC_MEM_WRITE                UC_PROT_WRITE
UC_ARCH_MAX                 UC_HOOK_CODE                UC_MEM_WRITE_PROT           UC_QUERY_MODE
UC_ARCH_MIPS                UC_HOOK_INSN                UC_MEM_WRITE_UNMAPPED       UC_QUERY_PAGE_SIZE
UC_ARCH_PPC                 UC_HOOK_INTR                UC_MILISECOND_SCALE         UC_SECOND_SCALE
UC_ARCH_SPARC               UC_HOOK_MEM_FETCH           UC_MODE_16                  UC_VERSION_EXTRA
UC_ARCH_X86                 UC_HOOK_MEM_FETCH_INVALID   UC_MODE_32                  UC_VERSION_MAJOR
UC_ERR_ARCH                 UC_HOOK_MEM_FETCH_PROT      UC_MODE_64                  UC_VERSION_MINOR
UC_ERR_ARG                  UC_HOOK_MEM_FETCH_UNMAPPED  UC_MODE_ARM                 Uc
UC_ERR_EXCEPTION            UC_HOOK_MEM_INVALID         UC_MODE_BIG_ENDIAN          UcError
UC_ERR_FETCH_PROT           UC_HOOK_MEM_PROT            UC_MODE_LITTLE_ENDIAN       arm64_const
UC_ERR_FETCH_UNALIGNED      UC_HOOK_MEM_READ            UC_MODE_MCLASS              arm_const
UC_ERR_FETCH_UNMAPPED       UC_HOOK_MEM_READ_AFTER      UC_MODE_MICRO               debug
UC_ERR_HANDLE               UC_HOOK_MEM_READ_INVALID    UC_MODE_MIPS3               m68k_const
UC_ERR_HOOK                 UC_HOOK_MEM_READ_PROT       UC_MODE_MIPS32              mips_const
UC_ERR_HOOK_EXIST           UC_HOOK_MEM_READ_UNMAPPED   UC_MODE_MIPS32R6            sparc_const
UC_ERR_INSN_INVALID         UC_HOOK_MEM_UNMAPPED        UC_MODE_MIPS64              uc_arch_supported
UC_ERR_MAP                  UC_HOOK_MEM_VALID           UC_MODE_PPC32               uc_version
UC_ERR_MODE                 UC_HOOK_MEM_WRITE           UC_MODE_PPC64               unicorn
UC_ERR_NOMEM                UC_HOOK_MEM_WRITE_INVALID   UC_MODE_QPX                 unicorn_const
UC_ERR_OK                   UC_HOOK_MEM_WRITE_PROT      UC_MODE_SPARC32             version_bind
UC_ERR_READ_PROT            UC_HOOK_MEM_WRITE_UNMAPPED  UC_MODE_SPARC64             x86_const
UC_ERR_READ_UNALIGNED       UC_MEM_FETCH                UC_MODE_THUMB               
UC_ERR_READ_UNMAPPED        UC_MEM_FETCH_PROT           UC_MODE_V8                  
UC_ERR_RESOURCE             UC_MEM_FETCH_UNMAPPED       UC_MODE_V9                  

niektóre stałe występujące w module unicorn.x86_const:

UC_X86_REG_EAX
UC_X86_REG_RIP
UC_X86_REG_RAX

mu = Uc(arch, mode) np. mu = Uc(UC_ARCH_X86, UC_MODE_64) - dostajemy instancję UE

mu.mem_map(ADDRESS, 4096) - mapujemy pamięć
mu.mem_write(ADDRESS, DATA) - zapisujemy do pamięci
tmp = mu.mem_read(ADDRESS, SIZE) - odczytujemy z pamięci

mu.reg_write(UC_X86_REG_ECX, 0x0) - ustawiamy rejestr na konkretną wartość. Tutaj konkretnie - ustawiamy rejestr ECX na 0x0
r_esp = mu.reg_read(UC_X86_REG_ESP) odczytujemy stan rejestru - tutaj konkretnie ESP

mu.emu_start(ADDRESS_START, ADDRESS_END) - uruchamiamy kod

traking wykonywanych instrukcji:

def hook_code(uc, address, size, user_data):  
    print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' %(address, size))  

mu.hook_add(UC_HOOK_CODE, hook_code)
  • uc - wskazuje na naszą instancję
  • address - adres instrukcji która się wykona
  • size - rozmiar instrukcji która się wykona

przydatne funkcje

def read(name):
    with open(name) as f:
        return f.read()
        
def u32(data): #zamien ciag 4 bajtow na liczbe w formacie little-endian
    return struct.unpack("I", data)[0]
    
def p32(num): #zamien liczbe w formacie little-endian na ciag 4 bajtow
    return struct.pack("I", num)

zadanie pierwsze

download

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  void *v3; // rbp@1
  int v4; // ebx@1
  signed __int64 v5; // r8@2
  char v6; // r9@3
  __int64 v7; // r8@3
  char v8; // cl@3
  __int64 v9; // r9@5
  int a2a; // [sp+Ch] [bp-1Ch]@3

  v3 = &encrypted_flag;
  v4 = 0;
  setbuf(stdout, 0LL);
  printf("The flag is: ", 0LL);
  while ( 1 )
  {
    LODWORD(v5) = 0;
    do
    {
      a2a = 0;
      fibonacci(v4 + v5, &a2a);
      v8 = v7;
      v5 = v7 + 1;
    }
    while ( v5 != 8 );
    v4 += 8;
    if ( (unsigned __int8)(a2a << v8) == v6 )
      break;
    v3 = (char *)v3 + 1;
    _IO_putc((char)(v6 ^ ((_BYTE)a2a << v8)), stdout);
    v9 = *((char *)v3 - 1);
  }
  _IO_putc(10, stdout);
  return 0LL;
}
unsigned int __fastcall fibonacci(int i, _DWORD *a2)
{
  _DWORD *v2; // rbp@1
  unsigned int v3; // er12@3
  unsigned int result; // eax@3
  unsigned int v5; // edx@3
  unsigned int v6; // esi@3
  unsigned int v7; // edx@4

  v2 = a2;
  if ( i )
  {
    if ( i == 1 )
    {
      result = fibonacci(0, a2);
      v5 = result - ((result >> 1) & 0x55555555);
      v6 = ((result - ((result >> 1) & 0x55555555)) >> 2) & 0x33333333;
    }
    else
    {
      v3 = fibonacci(i - 2, a2);
      result = v3 + fibonacci(i - 1, a2);
      v5 = result - ((result >> 1) & 0x55555555);
      v6 = ((result - ((result >> 1) & 0x55555555)) >> 2) & 0x33333333;
    }
    v7 = v6 + (v5 & 0x33333333) + ((v6 + (v5 & 0x33333333)) >> 4);
    *v2 ^= ((BYTE1(v7) & 0xF) + (v7 & 0xF) + (unsigned __int8)((((v7 >> 8) & 0xF0F0F) + (v7 & 0xF0F0F0F)) >> 16)) & 1;
  }
  else
  {
    *a2 ^= 1u;
    result = 1;
  }
  return result;
}

funkcja main:

.text:00000000004004E0 main            proc near               ; DATA XREF: start+1D�o
.text:00000000004004E0
.text:00000000004004E0 var_1C          = dword ptr -1Ch
.text:00000000004004E0
.text:00000000004004E0                 push    rbp
.text:00000000004004E1                 push    rbx
.text:00000000004004E2                 xor     esi, esi        ; buf
.text:00000000004004E4                 mov     ebp, offset unk_4007E1
.text:00000000004004E9                 xor     ebx, ebx
.text:00000000004004EB                 sub     rsp, 18h
.text:00000000004004EF                 mov     rdi, cs:stdout  ; stream
.text:00000000004004F6                 call    _setbuf
.text:00000000004004FB                 mov     edi, offset format ; "The flag is: "
.text:0000000000400500                 xor     eax, eax
.text:0000000000400502                 call    _printf
.text:0000000000400507                 mov     r9d, 49h
.text:000000000040050D                 nop     dword ptr [rax]
.text:0000000000400510
.text:0000000000400510 loc_400510:                             ; CODE XREF: main+8A�j
.text:0000000000400510                 xor     r8d, r8d
.text:0000000000400513                 jmp     short loc_40051B
.text:0000000000400513 ; ---------------------------------------------------------------------------
.text:0000000000400515                 align 8
.text:0000000000400518
.text:0000000000400518 loc_400518:                             ; CODE XREF: main+67�j
.text:0000000000400518                 mov     r9d, edi
.text:000000000040051B
.text:000000000040051B loc_40051B:                             ; CODE XREF: main+33�j
.text:000000000040051B                 lea     edi, [rbx+r8]
.text:000000000040051F                 lea     rsi, [rsp+28h+var_1C]
.text:0000000000400524                 mov     [rsp+28h+var_1C], 0
.text:000000000040052C                 call    fibonacci
.text:0000000000400531                 mov     edi, [rsp+28h+var_1C]
.text:0000000000400535                 mov     ecx, r8d
.text:0000000000400538                 add     r8, 1
.text:000000000040053C                 shl     edi, cl
.text:000000000040053E                 mov     eax, edi
.text:0000000000400540                 xor     edi, r9d
.text:0000000000400543                 cmp     r8, 8
.text:0000000000400547                 jnz     short loc_400518
.text:0000000000400549                 add     ebx, 8
.text:000000000040054C                 cmp     al, r9b
.text:000000000040054F                 mov     rsi, cs:stdout  ; fp
.text:0000000000400556                 jz      short loc_400570
.text:0000000000400558                 movsx   edi, dil        ; c
.text:000000000040055C                 add     rbp, 1
.text:0000000000400560                 call    __IO_putc
.text:0000000000400565                 movzx   r9d, byte ptr [rbp-1]
.text:000000000040056A                 jmp     short loc_400510
.text:000000000040056A ; ---------------------------------------------------------------------------
.text:000000000040056C                 align 10h
.text:0000000000400570
.text:0000000000400570 loc_400570:                             ; CODE XREF: main+76�j
.text:0000000000400570                 mov     edi, 0Ah        ; c
.text:0000000000400575                 call    __IO_putc
.text:000000000040057A                 add     rsp, 18h
.text:000000000040057E                 xor     eax, eax
.text:0000000000400580                 pop     rbx
.text:0000000000400581                 pop     rbp
.text:0000000000400582                 retn
.text:0000000000400582 main            endp

funkcja fibonacci:

.text:0000000000400670 fibonacci       proc near               ; CODE XREF: main+4C�p
.text:0000000000400670                                         ; fibonacci+19�p ...
.text:0000000000400670                 test    edi, edi
.text:0000000000400672                 push    r12
.text:0000000000400674                 push    rbp
.text:0000000000400675                 mov     rbp, rsi
.text:0000000000400678                 push    rbx
.text:0000000000400679                 jz      short loc_4006F8
.text:000000000040067B                 cmp     edi, 1
.text:000000000040067E                 mov     ebx, edi
.text:0000000000400680                 jz      loc_400710
.text:0000000000400686                 lea     edi, [rdi-2]
.text:0000000000400689                 call    fibonacci
.text:000000000040068E                 lea     edi, [rbx-1]
.text:0000000000400691                 mov     r12d, eax
.text:0000000000400694                 mov     rsi, rbp
.text:0000000000400697                 call    fibonacci
.text:000000000040069C                 add     eax, r12d
.text:000000000040069F                 mov     edx, eax
.text:00000000004006A1                 mov     ebx, eax
.text:00000000004006A3                 shr     edx, 1
.text:00000000004006A5                 and     edx, 55555555h
.text:00000000004006AB                 sub     ebx, edx
.text:00000000004006AD                 mov     ecx, ebx
.text:00000000004006AF                 mov     edx, ebx
.text:00000000004006B1                 shr     ecx, 2
.text:00000000004006B4                 and     ecx, 33333333h
.text:00000000004006BA                 mov     esi, ecx
.text:00000000004006BC
.text:00000000004006BC loc_4006BC:                             ; CODE XREF: fibonacci+C2�j
.text:00000000004006BC                 and     edx, 33333333h
.text:00000000004006C2                 lea     ecx, [rsi+rdx]
.text:00000000004006C5                 mov     edx, ecx
.text:00000000004006C7                 shr     edx, 4
.text:00000000004006CA                 add     edx, ecx
.text:00000000004006CC                 mov     esi, edx
.text:00000000004006CE                 and     edx, 0F0F0F0Fh
.text:00000000004006D4                 shr     esi, 8
.text:00000000004006D7                 and     esi, 0F0F0Fh
.text:00000000004006DD                 lea     ecx, [rsi+rdx]
.text:00000000004006E0                 mov     edx, ecx
.text:00000000004006E2                 shr     edx, 10h
.text:00000000004006E5                 add     edx, ecx
.text:00000000004006E7                 and     edx, 1
.text:00000000004006EA                 xor     [rbp+0], edx
.text:00000000004006ED                 pop     rbx
.text:00000000004006EE                 pop     rbp
.text:00000000004006EF                 pop     r12
.text:00000000004006F1                 retn
.text:00000000004006F1 ; ---------------------------------------------------------------------------
.text:00000000004006F2                 align 8
.text:00000000004006F8
.text:00000000004006F8 loc_4006F8:                             ; CODE XREF: fibonacci+9�j
.text:00000000004006F8                 mov     edx, 1
.text:00000000004006FD                 xor     [rbp+0], edx
.text:0000000000400700                 mov     eax, 1
.text:0000000000400705                 pop     rbx
.text:0000000000400706                 pop     rbp
.text:0000000000400707                 pop     r12
.text:0000000000400709                 retn
.text:0000000000400709 ; ---------------------------------------------------------------------------
.text:000000000040070A                 align 10h
.text:0000000000400710
.text:0000000000400710 loc_400710:                             ; CODE XREF: fibonacci+10�j
.text:0000000000400710                 xor     edi, edi
.text:0000000000400712                 call    fibonacci
.text:0000000000400717                 mov     edx, eax
.text:0000000000400719                 mov     edi, eax
.text:000000000040071B                 shr     edx, 1
.text:000000000040071D                 and     edx, 55555555h
.text:0000000000400723                 sub     edi, edx
.text:0000000000400725                 mov     esi, edi
.text:0000000000400727                 mov     edx, edi
.text:0000000000400729                 shr     esi, 2
.text:000000000040072C                 and     esi, 33333333h
.text:0000000000400732                 jmp     short loc_4006BC
.text:0000000000400732 fibonacci       endp

adres 0x0000000000400670 w pamięci virtualnej ma offset 0x670 w pliku. czyli base = 0x0000000000400000

zadanie drugie

przenalizuj ten zobfuskowany shellcode za pomocą UE:

\x31\xd2\x52\xb8\xb7\xd8\x3e\x56\x05\x78\x56\x34\x12\x50\xb8\xde\xc0\xad\xde\x2d\xaf\x5e\x44\x70\x50\x6a\x0b\x58\x89\xd1\x89\xe3\x6a\x01\x5e\xcd\x80\x96\xcd\x80

tym razem architektura to x86_32

a@agnieszkab ~/ $ disasm 31d252b8b7d83e56057856341250b8dec0adde2daf5e4470506a0b5889d189e36a015ecd8096cd80
   0:    31 d2                    xor    edx, edx
   2:    52                       push   edx
   3:    b8 b7 d8 3e 56           mov    eax, 0x563ed8b7
   8:    05 78 56 34 12           add    eax, 0x12345678
   d:    50                       push   eax
   e:    b8 de c0 ad de           mov    eax, 0xdeadc0de
  13:    2d af 5e 44 70           sub    eax, 0x70445eaf
  18:    50                       push   eax
  19:    6a 0b                    push   0xb
  1b:    58                       pop    eax
  1c:    89 d1                    mov    ecx, edx
  1e:    89 e3                    mov    ebx, esp
  20:    6a 01                    push   0x1
  22:    5e                       pop    esi
  23:    cd 80                    int    0x80
  25:    96                       xchg   esi, eax
  26:    cd 80                    int    0x80

podpowiedź: instrukcja int 0x80 to bajty 0xcd 0x80. Można zrobić na te bajty hooka i odczytać odpowiednie rejestry. rejestr EAX przechowuje numer syscalla. lista syscalli. Argumenty syscalla są przechowywane kolejno w rejestrach EBX, ECX, EDX, ESI, EDI.

zadanie trzecie

download

int strcmp(char *a, char *b)
{
    //get length
    int len = 0;
    char *ptr = a;
    while(*ptr)
    {
        ptr++;
        len++;
    }
    
    //comparestrings
    for(int i=0; i<=len; i++)
    {
        if (a[i]!=b[i])
            return 1;
    }
    
    return 0;
}

__attribute__((stdcall))
int  super_function(int a, char *b)
{
    if (a==5 && !strcmp(b, "zegnam"))
    {
        return 1;
    }
    return 0;
}

int main()
{
    super_function(1, "witam");
}  

wywołaj funkcje super_function tak, aby zwróciła wartość 1 . Program jest 32 bitowy

asm:

.text:08048464 super_function  proc near               ; CODE XREF: main+16�p
.text:08048464
.text:08048464 arg_0           = dword ptr  8
.text:08048464 arg_4           = dword ptr  0Ch
.text:08048464
.text:08048464                 push    ebp
.text:08048465                 mov     ebp, esp
.text:08048467                 call    __x86_get_pc_thunk_ax
.text:0804846C                 add     eax, 1B94h
.text:08048471                 cmp     [ebp+arg_0], 5
.text:08048475                 jnz     short loc_8048494
.text:08048477                 lea     eax, (aZegnam - 804A000h)[eax] ; "zegnam"
.text:0804847D                 push    eax
.text:0804847E                 push    [ebp+arg_4]
.text:08048481                 call    strcmp
.text:08048486                 add     esp, 8
.text:08048489                 test    eax, eax
.text:0804848B                 jnz     short loc_8048494
.text:0804848D                 mov     eax, 1
.text:08048492                 jmp     short locret_8048499
.text:08048494 ; ---------------------------------------------------------------------------
.text:08048494
.text:08048494 loc_8048494:                            ; CODE XREF: super_function+11�j
.text:08048494                                         ; super_function+27�j
.text:08048494                 mov     eax, 0
.text:08048499
.text:08048499 locret_8048499:                         ; CODE XREF: super_function+2E�j
.text:08048499                 leave
.text:0804849A                 retn    8
.text:0804849A super_function  endp

adres 0x08048464 w pamięci virtualnej będzie miał offset w pliku 0x464 . Czyli base = 0x08048000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment