# Shellcodes

Use the given source code written in C++:
+ [shellcode_task_step1.cpp](shellcode_task_step1.cpp)

## 32 bit version

1. Open Visual Studio command prompt (x86). Compile the `shellcode_task_step1.cpp` to assembly, with the help of commands:

```
 cl /c /FA <file_name>.cpp
```

2. You will get the assembly version of the app:`<file_name>.asm`. First use it as is, and test if you can get the output EXE.

```
ml <file_name>.asm
```
Since we use FS register, the assembler will print an error. In order to silence it out, we need to add the following line on the top of our file:

```asm
assume fs:nothing
```
After this modification, the file should compile without issues.

Run the output exe and make sure that everything works fine.

3. First step of refactoring to the shellcode: we need to remove all the external dependencies. We will remove the automatically included libs.
Comment-out the lines:

```
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
```

Comment-out the the line including listing:

```
include listing.inc
```

Now the default entry point (`_mainCRTStartup`) will not be found by the linker (because it was in the included part). We need to link it giving the entry point explicitly:

```
ml /c <file_name>.asm
link <file_name>.obj /entry:main
```
Check if everything works fine. 
Open the resulting PE in PE-bear. What has changed comparing to the previous application? What are the more things we need to get rid of, in order to obtain a shellcode?

>Answer: relocations (make code position-independent)

4. To make the shellcode position-independent, we cannot have any data stored in a separate section. We can only use the `.text` section for everything. So far, our strings are stored in the `.data` section. So, we need to refactor the assembly code to inline them.

Example of inlining a string:

+ we copy the string from the data segment, and paste just before the line where it was pushed on the stack. We push it on the stack by making a call after the string:

```asm
	call after_kernel32_str
DB	'k', 00H, 'e', 00H, 'r', 00H, 'n', 00H, 'e', 00H, 'l', 00H
	DB	'3', 00H, '2', 00H, '.', 00H, 'd', 00H, 'l', 00H, 'l', 00H, 00H
	DB	00H
	ORG $+2
after_kernel32_str:
	;push	OFFSET $SG89718
 ```

After inlining all the strings we should compile the application again, by:

```
ml /c <file_name>.asm
link <file_name>.obj /entry:main
```
Sometimes inlining the strings will make a distance between instructions too big, and prevent short jumps. We need to fix it manually, by changing the short jump to long jump.

Example:

```asm
	jmp	SHORT $LN1@main
```

change to:


```asm
	jmp	$LN1@main
```

5. Cuting-out and testing the shellcode.
+ Open the final version of the app in PE-bear. Notice that now the exe should have no import table, as well as no relocations table.
+ Dump the `.text` section from the file using PE-bear
+ Test the shellcode, by running it by `runshc32.exe` from [pe_to_shellcode package](https://github.com/hasherezade/pe_to_shellcode/releases)
+ If everything went fine, the shellcode should run the same way as the EXE

## 64 bit version

Making a 64 bit version of the shellcode will be analogical, but some additional steps have to be taken.

1. First, open Visual Studio command prompt (x64). Compile the `shellcode_task_step1.cpp` to assembly, with the help of commands:

```
 cl /c /FA <file_name>.cpp
```

2. You will get the assembly version of the app:`<file_name>.asm`. First use it as is, and test if you can get the output EXE.

```
ml64 <file_name>.asm
```
This time we get several errors. It is due to the fact that the generated listing is not fully compatibile with MASM, and we need to fix all the compatibility issues manually. We will get the similar list of errors:

```
shellcode_task_step1.asm(75) : error A2006:undefined symbol : FLAT
shellcode_task_step1.asm(86) : error A2006:undefined symbol : FLAT
shellcode_task_step1.asm(98) : error A2006:undefined symbol : FLAT
shellcode_task_step1.asm(116) : error A2006:undefined symbol : FLAT
shellcode_task_step1.asm(120) : error A2006:undefined symbol : FLAT
shellcode_task_step1.asm(132) : error A2006:undefined symbol : FLAT
shellcode_task_step1.asm(133) : error A2006:undefined symbol : FLAT
shellcode_task_step1.asm(375) : error A2027:operand must be a memory expression
shellcode_task_step1.asm(30) : error A2006:undefined symbol : $LN16
shellcode_task_step1.asm(31) : error A2006:undefined symbol : $LN16
shellcode_task_step1.asm(36) : error A2006:undefined symbol : $LN13
shellcode_task_step1.asm(37) : error A2006:undefined symbol : $LN13
shellcode_task_step1.asm(41) : error A2006:undefined symbol : $LN7
shellcode_task_step1.asm(42) : error A2006:undefined symbol : $LN7
```
+ We need to manually remove the word `FLAT` from the asm file. Just replace `FLAT:` with nothing.
+ We need to remove the `pdata` and `xdata` segments
+ We need to fix the reference to `gs` register to `gs:[96]`

from:

```asm
mov	rax, QWORD PTR gs:96
```

to:

```asm
mov	rax, QWORD PTR gs:[96]
```

Now the file should assemble properly. Run the resulting executable and check it in PE-bear.

3. Remove the dependencies analogically like in the 32 bit version. Compile the file:

```
ml64 /c <file_name>.asm
link <file_name>.obj /entry:main
```

4. Inline all the strings. It will be similar like in the 32-bit version, but this time arguments are supplied by the registers, rather than being pushed on the stack.
That's why you need to pop their offsets into appropriate registers. Example of inlined string for the 64 bit version:

```asm
call after_msgbox_str
	DB	'MessageBoxW', 00H
after_msgbox_str:
	pop rdx
	;lea	rdx, OFFSET $SG90389
	mov	rcx, QWORD PTR u32_dll$[rsp]
	call	QWORD PTR _GetProcAddress$[rsp]
```

5.  Cuting-out and testing the shellcode - analogical to the 32-bit version:

+ Open the final version of the app in PE-bear. Notice that now the exe should have no import table, as well as no relocations table.
+ Dump the `.text` section from the file using PE-bear
+ Test the shellcode, by running it by `runshc64.exe` from [pe_to_shellcode package](https://github.com/hasherezade/pe_to_shellcode/releases)
+ If everything went fine, the shellcode should run the same way as the EXE
