SRL Archive - General

Simba + Assembly


Brandon

2014-08-11 21:35:43

So.. I was messing around with making payloads and decided to try running some in Simba.. Turns out it works.. I converted all the code to HEX/OP-codes using: https://defuse.ca/online-x86-assembler.htm#disassembly

Get Current Process ID (doesn't seem to work.. Works in C/C++ though):

type fptr = Function: Integer;

var
get_pid: array of byte;

begin
get_pid := [$31, $DB, $55, $89, $E5, $64, $A1, $24, $00, $00, $00, $89, $EC, $5D, $C3, $E8, $EE, $FF, $FF, $FF];
writeln(fptr(get_pid)());
end.


xor ebx, ebx

func:
push ebp
mov ebp, esp

mov eax, dword [FS:0x20]

mov esp, ebp
pop ebp
ret

call func


It just shows 2 msg boxes..

type fptr = Function: Integer;

var
msg_then_access_violate: array of byte;
msg_then_exit_process: array of byte;
both: array of byte;
I: Integer;
begin
msg_then_access_violate := [$31, $db, $eb, $55, $64, $8b, $7b,
$30, $8b, $7f, $0c, $8b, $7f, $1c, $8b, $47, $08, $8b, $77, $20, $8b, $3f,
$80, $7e, $0c, $33, $75, $f2, $89, $c7, $03, $78, $3c, $8b, $57, $78, $01,
$c2, $8b, $7a, $20, $01, $c7, $89, $dd, $8b, $34, $af, $01, $c6, $45, $8b,
$4c, $24, $04, $39, $0e, $75, $f2, $8b, $4c, $24, $08, $39, $4e, $04, $75,
$e9, $8b, $7a, $24, $01, $c7, $66, $8b, $2c, $6f, $8b, $7a, $1c, $01, $c7,
$8b, $7c, $af, $fc, $01, $f8, $c3, $68, $4c, $69, $62, $72, $68, $4c, $6f,
$61, $64, $e8, $9c, $ff, $ff, $ff, $31, $c9, $66, $b9, $33, $32, $51, $68,
$75, $73, $65, $72, $54, $ff, $d0, $50, $68, $72, $6f, $63, $41, $68, $47,
$65, $74, $50, $e8, $7d, $ff, $ff, $ff, $59, $59, $59, $68, $f0, $86, $17,
$04, $c1, $2c, $24, $04, $68, $61, $67, $65, $42, $68, $4d, $65, $73, $73,
$54, $51, $ff, $d0, $53, $53, $53, $53, $ff, $d0];

msg_then_exit_process := [$31, $d2, $b2, $30, $64, $8b, $12, $8b, $52, $0c, $8b, $52, $1c, $8b, $42,
$08, $8b, $72, $20, $8b, $12, $80, $7e, $0c, $33, $75, $f2, $89, $c7, $03,
$78, $3c, $8b, $57, $78, $01, $c2, $8b, $7a, $20, $01, $c7, $31, $ed, $8b,
$34, $af, $01, $c6, $45, $81, $3e, $46, $61, $74, $61, $75, $f2, $81, $7e,
$08, $45, $78, $69, $74, $75, $e9, $8b, $7a, $24, $01, $c7, $66, $8b, $2c,
$6f, $8b, $7a, $1c, $01, $c7, $8b, $7c, $af, $fc, $01, $c7, $68, $79, $74,
$65, $01, $68, $6b, $65, $6e, $42, $68, $20, $42, $72, $6f, $89, $e1, $fe,
$49, $0b, $31, $c0, $51, $50, $ff, $d7];

both := msg_then_access_violate;
SetLength(both, length(msg_then_access_violate) + length(msg_then_exit_process));
for I := Length(msg_then_access_violate) To High(Both) Do
both[I] := msg_then_exit_process[I - Length(msg_then_access_violate)];

fptr(both)();
writeln(fptr(msg_then_access_violate)());
writeln(fptr(msg_then_exit_process)());
end.

I tried writing my own but it didn't work:

cmp_str_insensitive:
push ebp
mov ebp, esp

mov esi, [ebp + 0x08]
mov edi, [ebp + 0x0C]
mov edx, [ebp + 0x10]
xor ecx, ecx

cmp_str_for:
mov ax, [esi + ecx * 0x02]
mov bx, [edi + ecx * 0x02]
inc ecx

cmp ax, 0x61
jl cmp_ins_cont_1
cmp ax, 0x7A
jg cmp_ins_cont_1
sub ax, 0x20

cmp_ins_cont_1:
cmp bx, 0x61
jl cmp_ins_cont_2
cmp bx, 0x7A
jg cmp_ins_cont_2
sub bx, 0x20

cmp_ins_cont_2:
cmp ax, bx
jne cmp_mem_diff
cmp ax, 0
je cmp_mem_same
jmp cmp_str_for


cmp_mem_diff:
mov eax, 0
jmp cmp_mem_done

cmp_mem_same:
mov eax, 1

cmp_mem_done:

mov esp, ebp
pop ebp
ret 0x0C

isK32:
push ebp
mov ebp, esp
mov eax, [ebp + 0x08]

sub esp, 26
mov edx, esp
mov word ptr[edx + 0x00], 75
mov word ptr[edx + 0x02], 69
mov word ptr[edx + 0x04], 82
mov word ptr[edx + 0x06], 78
mov word ptr[edx + 0x08], 69
mov word ptr[edx + 0xE0], 76
mov word ptr[edx + 0x10], 51
mov word ptr[edx + 0x12], 50
mov word ptr[edx + 0x14], 46
mov word ptr[edx + 0x16], 68
mov word ptr[edx + 0x18], 76
mov word ptr[edx + 0x1A], 76
mov word ptr[edx + 0x00], 0

add esp, 26
mov esp, ebp
pop ebp
ret

Get_Kernel32_Address:
push ebp
mov ebp, esp

xor edx, edx
mov edx, [FS:0x30]
mov edx, [edx + 0x0C]
mov edx, [edx + 0x14]

gka_for:
mov esi, [edx + 0x28]
cmp esi, 0
je fail

push edx
push esi
call isK32
pop esi
pop edx

cmp eax, 1
je success
mov edx, [edx]
jmp gka_for

fail:
mov eax, 0
jmp done

success:
mov eax, [edx + 0x10]

done:
mov esp, ebp
pop ebp
ret

call Get_Kernel32_Address



Does it work for anyone else? Or just me :l

Sin

2014-08-11 21:37:56

Blank Error box came up, then received a fatal error with the code 'Broken Byte' at which point Simba crashed.

Ashaman88

2014-08-11 21:41:25

From: Sin
Blank Error box came up, then received a fatal error with the code 'Broken Byte' at which point Simba crashed.


Way to break my running script @Brandon;!

Brandon

2014-08-11 21:54:00

From: Ashaman88
Way to break my running script @Brandon;!


Lol. Oops. Forgot to mention that it EXITS the process after running fptr(BOTH)().

stein3

2014-08-11 22:03:03

What assembly language is that? There's some weird notation I've never seen before, but I've only really gone in-depth with x64.

Brandon

2014-08-11 22:22:25

From: nategr8ns
What assembly language is that? There's some weird notation I've never seen before, but I've only really gone in-depth with x64.


What do you mean? That's x86 Intel syntax. It looks the exact same for x64. Only different would be the registers.

What does the assembly you do look like :S


As for the "Simba" code, it's just the x86 assembly converted to the OP-codes/hex.

bonsai

2014-08-12 04:14:40


nielsie95

2014-08-12 04:53:05

Make sure you use VirtualAlloc/VirtualProtect to ensure you allocate memory that can be executed. We once looked into using a method similar to this to speed up color comparisons. Pretty cool indeed :)

stein3

2014-08-13 00:18:41

From: Brandon
What do you mean? That's x86 Intel syntax. It looks the exact same for x64. Only different would be the registers.

What does the assembly you do look like :S


As for the "Simba" code, it's just the x86 assembly converted to the OP-codes/hex.


It looks the same except for lines like:
mov eax, dword [FS:0x20]

What's the significance of the length "dword" and the FS:? "Filesystem?"

Brandon

2014-08-13 02:40:08

From: nategr8ns
It looks the same except for lines like:
mov eax, dword [FS:0x20]

What's the significance of the length "dword" and the FS:? "Filesystem?"


mov eax, dword[FS: 0x20] means to retrieve the value in the FS register at offset 0x20. Move 32 bits of it (an int) into eax.

(http://thestarman.pcministry.com/asm/debug/Segments.html)

If I did:

mov ax, word[FS: 0x20] it'd move only 16 bits of it (a short)
mov ah, byte[FS: 0x20] it'd move only 8 bits of it (a char)


Now when using the mov instruction on non-register data you need to provide a size. In this case, the "dword" isn't needed. Why? Because the assembler already knows that eax is a dword size register (32-bit). I just have a habit of putting the size explicitly from old times.


FS and GS are "Segment registers". On x86 Windows, the Kernel stores thread information and various other information in the FS register. On x64 Windows, it stores some of it in the GS register.

Both Linux and Windows use the FS and GS registers.


http://en.wikipedia.org/wiki/Win32_Thread_Information_Block

Skim through it.





Other uses:

Then there's the undocumented stuff like how to "hide" things in processes.. It uses the GS and FS registers. For example, WOW's warden would read the PEB table and scan for loaded modules. You could remove such modules from the table (without unloading them) and then add them back right before you exit the game.. Of course, they do more scans than just the PEB but you get the gist of it.. All in all, these registers are really important.

superuser

2014-08-13 05:54:19

Oh! The good ol' times!

mov ax,13h
int 10h

:)

stein3

2014-08-13 08:23:36

From: Brandon
mov eax, dword[FS: 0x20] means to retrieve the value in the FS register at offset 0x20. Move 32 bits of it (an int) into eax.

(http://thestarman.pcministry.com/asm/debug/Segments.html)

If I did:

mov ax, word[FS: 0x20] it'd move only 16 bits of it (a short)
mov ah, byte[FS: 0x20] it'd move only 8 bits of it (a char)


Now when using the mov instruction on non-register data you need to provide a size. In this case, the "dword" isn't needed. Why? Because the assembler already knows that eax is a dword size register (32-bit). I just have a habit of putting the size explicitly from old times.


FS and GS are "Segment registers". On x86 Windows, the Kernel stores thread information and various other information in the FS register. On x64 Windows, it stores some of it in the GS register.

Both Linux and Windows use the FS and GS registers.


http://en.wikipedia.org/wiki/Win32_Thread_Information_Block

Skim through it.





Other uses:

Then there's the undocumented stuff like how to "hide" things in processes.. It uses the GS and FS registers. For example, WOW's warden would read the PEB table and scan for loaded modules. You could remove such modules from the table (without unloading them) and then add them back right before you exit the game.. Of course, they do more scans than just the PEB but you get the gist of it.. All in all, these registers are really important.


Huh, ok. In x64 I used to just use separate mov instructions. I used to use movb, movw, movl, and movq for byte, word, long, and quad.
Maybe its Intel vs AMD? Although I thought one of them set up the x64 architecture and the other one used it.

The colon for an offset is also new to me.

Brandon

2014-08-13 11:32:51

From: nategr8ns
Huh, ok. In x64 I used to just use separate mov instructions. I used to use movb, movw, movl, and movq for byte, word, long, and quad.
Maybe its Intel vs AMD? Although I thought one of them set up the x64 architecture and the other one used it.

The colon for an offset is also new to me.



You describe AT&T "syntax" xD. Not "AMD".



void* GetLDR()
{
void* result = NULL;

#ifndef __x86_64__
#ifndef INTEL_SYNTAX
__asm //32-bit AT&T Syntax
{
movl result, %edx
movl %%FS:0x18, %%eax
movl 0x30(%%eax), %%eax
movl 0x0C(%%eax), %edx
};
#else
__asm //32-bit Intel Syntax.
{
mov edx, DWORD PTR[result]
mov eax, DWORD PTR[FS:0x18]
mov eax, DWORD PTR [eax + 0x30]
mov edx, DWORD PTR [eax + 0x0C]
};
#endif
#else
#ifndef INTEL_SYNTAX
__asm //64-bit AT&T Syntax
{
movq result, %rdx
movq %%GS:0x30, %%rax
movq 0x60(%%rax), %%rax
movq 0x18(%%rax), %rdx
};
#else
__asm //64-bit Intel Syntax.
{
mov rdx, QWORD PTR[result]
mov rax, QWORD PTR [GS:0x30]
mov rax, QWORD PTR [rax + 0x60]
mov rdx, QWORD PTR [rax + 0x18]
};
#endif
#endif
return result;
}

stein3

2014-08-13 21:48:35

From: Brandon
You describe AT&T "syntax" xD. Not "AMD".

The double percent-signs still seems off.

I'm pretty sure AMD 64 is not AT&T 64-bit.

http://en.wikipedia.org/wiki/X86-64

edit: I don't really know though. Maybe its platform dependent (I was doing it purely on linux) or maybe I'm just confused :p.

Brandon

2014-08-13 22:56:58

From: nategr8ns
The double percent-signs still seems off.
I'm pretty sure AMD 64 is not AT&T 64-bit.



The AMD64 architectures utilise the Intel syntax aka x86_64 as show above and here: http://vikaskumar.org/amd64/nobranch.htm

According to their ABI documentation, it is perfectly valid to ALSO use the AT&T syntax (gcc uses this).

Manual:
http://www.x86-64.org/documentation/abi-0.99.6.pdf

Page 17 has an example and 22 lists the registers.


AMD64 is not a syntax. It is an architecture. Intel & AT&T are the only designed "syntax-es" for native ASM that I'm aware of (might be wrong on this one).


The double percent signs aren't off. They are required for "inline" assembly in gcc's AT&T syntax (you can enable intel-syntax using -masm=intel) and accesses the real underlying registers rather than the I/O operands. I/O Operands use a single percent sign. To store into a register, it requires that I add an extra percent sign (which I hate). Since the above code is actually C code with inline assembly, it was required that I use the extra %. In a real assembler, you'd remove the extra %. http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s7

I know it looks stupid too which is why it's confusing but it has to be done ={ There's also this thing where gcc requires your assembly to be embedded into quotes (a string).. lol.


Example of actual gcc inline assembly that will run would look like this:


void* GetLDR()
{
void* result = NULL;

#ifdef INTEL_SYNTAX /**-masm=intel to use Intel-Syntax**/
asm (".intel_syntax noprefix\n");
#else
asm (".att_syntax noprefix\n"); /**Otherwise AT&T Syntax by default**/
#endif

#ifndef INTEL_SYNTAX
asm volatile //64-bit AT&T
(
"movq %%GS:0x30, %%rax\n"
"movq 0x60(%%rax), %%rax\n"
"movq 0x18(%%rax), %0\n" //%0 means use the first operand.
: "=r" (result) :: "rax" //result is the first operand. It's stored in %0. rax is the clobber register.
);
#else
asm volatile //64-bit Intel
(
"mov rax, QWORD PTR [GS:0x30]\n\t"
"mov rax, QWORD PTR [rax + 0x60]\n\t"
"mov %0, QWORD PTR [rax + 0x18]\n" //%0 means use the first operand.
: "=r" (result) :: "rax" //result is the first operand. It's stored in %0. rax is the clobber register.
);
#endif
return result; //result will now hold the address of the PEB structure's LDR offset.
}


I was just too lazy to actually quote the asm and add the clobber registers.. Too much work :l I had also removed it to make it easier to see the relationship between the two syntax-es without the mumbo-jumbo.. Guess not ={

stein3

2014-08-14 08:44:37

Haha, well thanks for all the info. I never did it inline.
I pulled up some old lectures from the class I took on lower-level programming just for kicks. Here are some assembly snippets:

sum: 
pushl %ebp
movl %esp,%ebp
movl 12(%ebp),%eax
addl 8(%ebp),%eax
movl %ebp,%esp
popl %ebp
ret

swap: 
movl (%rdi), %edx
movl (%rsi), %eax
movl %eax, (%rdi)
movl %edx, (%rsi)
retq

and something else random in IA32
logical: 
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
xorl 12(%ebp),%eax
sarl $17,%eax
andl $8185,%eax
movl %ebp,%esp
popl %ebp
ret

an example that actually seems useful, returns the absolute difference between two numbers
absdiff: 
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl 12(%ebp), %eax
cmpl %eax, %edx
jle .L7
subl %eax, %edx
movl %edx, %eax

.L8:
leave
ret

.L7:
subl %edx, %eax
jmp .L8