CTF中的AEG(七) 对aeg题目源码分析 华为云专场-pwn_game

首先当然是dockerfile

FROM ubuntu:16.04
#是基于Ubuntu16.04

RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.tuna.tsinghua.edu.cn/g" /etc/apt/sources.list && \
    apt-get update && apt-get -y dist-upgrade && \
    apt-get install -y lib32z1 xinetd && \
    apt-get install -y gcc && \
    apt-get install -y build-essential
#换了一下源,然后更新软件包,下载了一些东西

RUN useradd -m ctf
#创建了用户ctf

WORKDIR /home/ctf
#在/home/ctf目录下去工作

COPY ./ctf.xinetd /etc/xinetd.d/ctf
COPY ./start.sh /start.sh
RUN echo "Blocked by ctf_xinetd" > /etc/banner_fail
#拷贝进去

RUN chmod +x /start.sh
#给start.sh一个执行权限

COPY ./bin/ /home/ctf/
#直接把bin文件都拷进去了

RUN chown -R root:ctf /home/ctf && \
    chmod -R 750 /home/ctf && \
    chmod 740 /home/ctf/flag_dir/flag
#把ctf目录,flag文件等都给了个权限

CMD ["/start.sh"]
#执行start.sh

EXPOSE 9999
#开放了9999端口

start.sh

#!/bin/sh
# Add your startup script

# DO NOT DELETE
/etc/init.d/xinetd start;
sleep infinity;

依然是直接调用xinetd

ctf.xinted

service ctf
{
    disable = no
    socket_type = stream
    protocol    = tcp
    wait        = no
    user        = root
    type        = UNLISTED
    port        = 9999
    bind        = 0.0.0.0
    server      = /usr/sbin/chroot
    # replace helloworld to your program
    server_args = --userspec=1000:1000 / /home/ctf/run.sh
    banner_fail = /etc/banner_fail
    # safety options
    per_source	= 10 # the maximum instances of this service per source IP address
    rlimit_cpu	= 20 # the maximum number of CPU seconds that the service may use
    #rlimit_as  = 1024M # the Address Space resource limit for the service
    #access_times = 2:00-9:00 12:00-24:00
}

chroot隔离了一下,然后启动run.sh

run.sh

#!/bin/bash
cd /home/ctf
./run_aeg_yeah

启动run_aeg_yeah

run_aeg_yeah是个ELF可执行程序文件
ida看看

进去发现不知道是一堆什么玩意
查找字符串之后
在这里插入图片描述发现是python写的然后打包的python

那github找个脚本

"""
PyInstaller Extractor v2.0 (Supports pyinstaller 4.7, 4.6, 4.5.1, 4.5, 4.4, 4.3, 4.2, 4.1, 4.0, 3.6, 3.5, 3.4, 3.3, 3.2, 3.1, 3.0, 2.1, 2.0)
Author : Extreme Coders
E-mail : extremecoders(at)hotmail(dot)com
Web    : https://0xec.blogspot.com
Date   : 26-March-2020
Url    : https://github.com/extremecoders-re/pyinstxtractor

For any suggestions, leave a comment on
https://forum.tuts4you.com/topic/34455-pyinstaller-extractor/

This script extracts a pyinstaller generated executable file.
Pyinstaller installation is not needed. The script has it all.

For best results, it is recommended to run this script in the
same version of python as was used to create the executable.
This is just to prevent unmarshalling errors(if any) while
extracting the PYZ archive.

Usage : Just copy this script to the directory where your exe resides
        and run the script with the exe file name as a parameter

C:\path\to\exe\>python pyinstxtractor.py <filename>
$ /path/to/exe/python pyinstxtractor.py <filename>

Licensed under GNU General Public License (GPL) v3.
You are free to modify this source.

CHANGELOG
================================================

Version 1.1 (Jan 28, 2014)
-------------------------------------------------
- First Release
- Supports only pyinstaller 2.0

Version 1.2 (Sept 12, 2015)
-------------------------------------------------
- Added support for pyinstaller 2.1 and 3.0 dev
- Cleaned up code
- Script is now more verbose
- Executable extracted within a dedicated sub-directory

(Support for pyinstaller 3.0 dev is experimental)

Version 1.3 (Dec 12, 2015)
-------------------------------------------------
- Added support for pyinstaller 3.0 final
- Script is compatible with both python 2.x & 3.x (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)

Version 1.4 (Jan 19, 2016)
-------------------------------------------------
- Fixed a bug when writing pyc files >= version 3.3 (Thanks to Daniello Alto: https://github.com/Djamana)

Version 1.5 (March 1, 2016)
-------------------------------------------------
- Added support for pyinstaller 3.1 (Thanks to Berwyn Hoyt for reporting)

Version 1.6 (Sept 5, 2016)
-------------------------------------------------
- Added support for pyinstaller 3.2
- Extractor will use a random name while extracting unnamed files.
- For encrypted pyz archives it will dump the contents as is. Previously, the tool would fail.

Version 1.7 (March 13, 2017)
-------------------------------------------------
- Made the script compatible with python 2.6 (Thanks to Ross for reporting)

Version 1.8 (April 28, 2017)
-------------------------------------------------
- Support for sub-directories in .pyz files (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)

Version 1.9 (November 29, 2017)
-------------------------------------------------
- Added support for pyinstaller 3.3
- Display the scripts which are run at entry (Thanks to Michael Gillespie @ malwarehunterteam for the feature request)

Version 2.0 (March 26, 2020)
-------------------------------------------------
- Project migrated to github
- Supports pyinstaller 3.6
- Added support for Python 3.7, 3.8
- The header of all extracted pyc's are now automatically fixed
"""

from __future__ import print_function
import os
import struct
import marshal
import zlib
import sys
from uuid import uuid4 as uniquename

# imp is deprecated in Python3 in favour of importlib
if sys.version_info.major == 3:
    from importlib.util import MAGIC_NUMBER
    pyc_magic = MAGIC_NUMBER
else:
    import imp
    pyc_magic = imp.get_magic()


class CTOCEntry:
    def __init__(self, position, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name):
        self.position = position
        self.cmprsdDataSize = cmprsdDataSize
        self.uncmprsdDataSize = uncmprsdDataSize
        self.cmprsFlag = cmprsFlag
        self.typeCmprsData = typeCmprsData
        self.name = name


class PyInstArchive:
    PYINST20_COOKIE_SIZE = 24           # For pyinstaller 2.0
    PYINST21_COOKIE_SIZE = 24 + 64      # For pyinstaller 2.1+
    MAGIC = b'MEI\014\013\012\013\016'  # Magic number which identifies pyinstaller

    def __init__(self, path):
        self.filePath = path


    def open(self):
        try:
            self.fPtr = open(self.filePath, 'rb')
            self.fileSize = os.stat(self.filePath).st_size
        except:
            print('[!] Error: Could not open {0}'.format(self.filePath))
            return False
        return True


    def close(self):
        try:
            self.fPtr.close()
        except:
            pass


    def checkFile(self):
        print('[+] Processing {0}'.format(self.filePath))

        searchChunkSize = 8192
        endPos = self.fileSize
        self.cookiePos = -1

        if endPos < len(self.MAGIC):
            print('[!] Error : File is too short or truncated')
            return False

        while True:
            startPos = endPos - searchChunkSize if endPos >= searchChunkSize else 0
            chunkSize = endPos - startPos

            if chunkSize < len(self.MAGIC):
                break

            self.fPtr.seek(startPos, os.SEEK_SET)
            data = self.fPtr.read(chunkSize)

            offs = data.rfind(self.MAGIC)

            if offs != -1:
                self.cookiePos = startPos + offs
                break

            endPos = startPos + len(self.MAGIC) - 1

            if startPos == 0:
                break

        if self.cookiePos == -1:
            print('[!] Error : Missing cookie, unsupported pyinstaller version or not a pyinstaller archive')
            return False

        self.fPtr.seek(self.cookiePos + self.PYINST20_COOKIE_SIZE, os.SEEK_SET)

        if b'python' in self.fPtr.read(64):
            print('[+] Pyinstaller version: 2.1+')
            self.pyinstVer = 21     # pyinstaller 2.1+
        else:
            self.pyinstVer = 20     # pyinstaller 2.0
            print('[+] Pyinstaller version: 2.0')

        return True


    def getCArchiveInfo(self):
        try:
            if self.pyinstVer == 20:
                self.fPtr.seek(self.cookiePos, os.SEEK_SET)

                # Read CArchive cookie
                (magic, lengthofPackage, toc, tocLen, self.pyver) = \
                struct.unpack('!8siiii', self.fPtr.read(self.PYINST20_COOKIE_SIZE))

            elif self.pyinstVer == 21:
                self.fPtr.seek(self.cookiePos, os.SEEK_SET)

                # Read CArchive cookie
                (magic, lengthofPackage, toc, tocLen, self.pyver, pylibname) = \
                struct.unpack('!8siiii64s', self.fPtr.read(self.PYINST21_COOKIE_SIZE))

        except:
            print('[!] Error : The file is not a pyinstaller archive')
            return False

        print('[+] Python version: {0}'.format(self.pyver))

        # Additional data after the cookie
        tailBytes = self.fileSize - self.cookiePos - (self.PYINST20_COOKIE_SIZE if self.pyinstVer == 20 else self.PYINST21_COOKIE_SIZE)
        
        # Overlay is the data appended at the end of the PE
        self.overlaySize = lengthofPackage + tailBytes
        self.overlayPos = self.fileSize - self.overlaySize
        self.tableOfContentsPos = self.overlayPos + toc
        self.tableOfContentsSize = tocLen

        print('[+] Length of package: {0} bytes'.format(lengthofPackage))
        return True


    def parseTOC(self):
        # Go to the table of contents
        self.fPtr.seek(self.tableOfContentsPos, os.SEEK_SET)

        self.tocList = []
        parsedLen = 0

        # Parse table of contents
        while parsedLen < self.tableOfContentsSize:
            (entrySize, ) = struct.unpack('!i', self.fPtr.read(4))
            nameLen = struct.calcsize('!iiiiBc')

            (entryPos, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name) = \
            struct.unpack( \
                '!iiiBc{0}s'.format(entrySize - nameLen), \
                self.fPtr.read(entrySize - 4))

            name = name.decode('utf-8').rstrip('\0')
            if len(name) == 0:
                name = str(uniquename())
                print('[!] Warning: Found an unamed file in CArchive. Using random name {0}'.format(name))

            self.tocList.append( \
                                CTOCEntry(                      \
                                    self.overlayPos + entryPos, \
                                    cmprsdDataSize,             \
                                    uncmprsdDataSize,           \
                                    cmprsFlag,                  \
                                    typeCmprsData,              \
                                    name                        \
                                ))

            parsedLen += entrySize
        print('[+] Found {0} files in CArchive'.format(len(self.tocList)))


    def _writeRawData(self, filepath, data):
        nm = filepath.replace('\\', os.path.sep).replace('/', os.path.sep).replace('..', '__')
        nmDir = os.path.dirname(nm)
        if nmDir != '' and not os.path.exists(nmDir): # Check if path exists, create if not
            os.makedirs(nmDir)

        with open(nm, 'wb') as f:
            f.write(data)


    def extractFiles(self):
        print('[+] Beginning extraction...please standby')
        extractionDir = os.path.join(os.getcwd(), os.path.basename(self.filePath) + '_extracted')

        if not os.path.exists(extractionDir):
            os.mkdir(extractionDir)

        os.chdir(extractionDir)

        for entry in self.tocList:
            basePath = os.path.dirname(entry.name)
            if basePath != '':
                # Check if path exists, create if not
                if not os.path.exists(basePath):
                    os.makedirs(basePath)

            self.fPtr.seek(entry.position, os.SEEK_SET)
            data = self.fPtr.read(entry.cmprsdDataSize)

            if entry.cmprsFlag == 1:
                data = zlib.decompress(data)
                # Malware may tamper with the uncompressed size
                # Comment out the assertion in such a case
                assert len(data) == entry.uncmprsdDataSize # Sanity Check

            if entry.typeCmprsData == b's':
                # s -> ARCHIVE_ITEM_PYSOURCE
                # Entry point are expected to be python scripts
                print('[+] Possible entry point: {0}.pyc'.format(entry.name))
                self._writePyc(entry.name + '.pyc', data)

            elif entry.typeCmprsData == b'M' or entry.typeCmprsData == b'm':
                # M -> ARCHIVE_ITEM_PYPACKAGE
                # m -> ARCHIVE_ITEM_PYMODULE
                # packages and modules are pyc files with their header's intact
                self._writeRawData(entry.name + '.pyc', data)

            else:
                self._writeRawData(entry.name, data)

                if entry.typeCmprsData == b'z' or entry.typeCmprsData == b'Z':
                    self._extractPyz(entry.name)


    def _writePyc(self, filename, data):
        with open(filename, 'wb') as pycFile:
            pycFile.write(pyc_magic)            # pyc magic

            if self.pyver >= 37:                # PEP 552 -- Deterministic pycs
                pycFile.write(b'\0' * 4)        # Bitfield
                pycFile.write(b'\0' * 8)        # (Timestamp + size) || hash 

            else:
                pycFile.write(b'\0' * 4)      # Timestamp
                if self.pyver >= 33:
                    pycFile.write(b'\0' * 4)  # Size parameter added in Python 3.3

            pycFile.write(data)


    def _extractPyz(self, name):
        dirName =  name + '_extracted'
        # Create a directory for the contents of the pyz
        if not os.path.exists(dirName):
            os.mkdir(dirName)

        with open(name, 'rb') as f:
            pyzMagic = f.read(4)
            assert pyzMagic == b'PYZ\0' # Sanity Check

            pycHeader = f.read(4) # Python magic value

            # Skip PYZ extraction if not running under the same python version
            if pyc_magic != pycHeader:
                print('[!] Warning: This script is running in a different Python version than the one used to build the executable.')
                print('[!] Please run this script in Python{0} to prevent extraction errors during unmarshalling'.format(self.pyver))
                print('[!] Skipping pyz extraction')
                return

            (tocPosition, ) = struct.unpack('!i', f.read(4))
            f.seek(tocPosition, os.SEEK_SET)

            try:
                toc = marshal.load(f)
            except:
                print('[!] Unmarshalling FAILED. Cannot extract {0}. Extracting remaining files.'.format(name))
                return

            print('[+] Found {0} files in PYZ archive'.format(len(toc)))

            # From pyinstaller 3.1+ toc is a list of tuples
            if type(toc) == list:
                toc = dict(toc)

            for key in toc.keys():
                (ispkg, pos, length) = toc[key]
                f.seek(pos, os.SEEK_SET)
                fileName = key

                try:
                    # for Python > 3.3 some keys are bytes object some are str object
                    fileName = fileName.decode('utf-8')
                except:
                    pass

                # Prevent writing outside dirName
                fileName = fileName.replace('..', '__').replace('.', os.path.sep)

                if ispkg == 1:
                    filePath = os.path.join(dirName, fileName, '__init__.pyc')

                else:
                    filePath = os.path.join(dirName, fileName + '.pyc')

                fileDir = os.path.dirname(filePath)
                if not os.path.exists(fileDir):
                    os.makedirs(fileDir)

                try:
                    data = f.read(length)
                    data = zlib.decompress(data)
                except:
                    print('[!] Error: Failed to decompress {0}, probably encrypted. Extracting as is.'.format(filePath))
                    open(filePath + '.encrypted', 'wb').write(data)
                else:
                    self._writePyc(filePath, data)


def main():
    if len(sys.argv) < 2:
        print('[+] Usage: pyinstxtractor.py <filename>')

    else:
        arch = PyInstArchive(sys.argv[1])
        if arch.open():
            if arch.checkFile():
                if arch.getCArchiveInfo():
                    arch.parseTOC()
                    arch.extractFiles()
                    arch.close()
                    print('[+] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1]))
                    print('')
                    print('You can now use a python decompiler on the pyc files within the extracted directory')
                    return

            arch.close()


if __name__ == '__main__':
    main()

跑一下拿到pyc

再用一下uncompyle6拿到python代码

uncompyle6 run_aeg_yeah.pyc

如下
我们分析一下

from random import *
import string, commands, hashlib, os

#创建文件夹
def prepare_dir(dirname):
    if os.path.exists(dirname) == False:
        try:
            os.makedirs(dirname)
        except Exception as e:
            print repr(e)
#repr函数还是很有意思的
#可以把对象转换成供解释去读取的对象
#>>> s = 'RUNOOB'
#>>> repr(s)
#"'RUNOOB'"
#>>> dict = {'runoob': 'runoob.com', 'google': 'google.com'};
#>>> repr(dict)
#"{'google': 'google.com', 'runoob': 'runoob.com'}"
#来自菜鸟教程


#commands.getstatusoutput就是执行里面的命令,然后返回其状态,跟输出,然后返回了输出
def do_command(cmd_line):
    status, output = commands.getstatusoutput(cmd_line)
    return output.strip()

#搞一个长长的字符串abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_
alpha_bet = string.ascii_letters + string.digits + '_'

#返回一个长度可控的随机字符串
def gen_rand_str(length):
    name = ''
    while len(name) < length:
        name += alpha_bet[randint(0, len(alpha_bet) - 1)]

    return name

#返回参数的md5值
def get_md5(data):
    temp = hashlib.md5(data)
    return temp.hexdigest()

#返回名字后面加了随机长度32的字符串的md5
def gen_name(name):
    return name + '_' + get_md5(gen_rand_str(32))

#显然是读文件
def read_file(filename, mode='rb'):
    file_r = open(filename, mode)
    data = file_r.read()
    file_r.close()
    return data

#显然是写文件
def write_file(filename, data, mode='wb'):
    file_w = open(filename, mode)
    file_w.write(data)
    file_w.close()

#直接pass?
def gen_func():
    pass

#randint从0-(val1 - 1)中随机出了一个数
#如果小于val2就返回true
#否则就返回false
def lucky_per(val1, val2):
    if randint(0, val1 - 1) < val2:
        return True
    return False

#重点就是replace_info函数
def replace_info(data):
	 #一个字符串加好多个列表
	 #起码来说第一个字符串显然是一会表达式的符号
    sym_str = '/%+-*^&|'
    sym_l = []
    sym_mid_l = []
    t_num_l = []
    lucky_v_l = []
    lucky_id_l = []
    
    #循环八次
    for i in range(8):
        if lucky_per(10, 1):
            sym_l.append(sym_str[randint(len(sym_str) - 1 - 3, len(sym_str) - 1)])
        else:
            sym_l.append(sym_str[randint(0, len(sym_str) - 1 - 3)])
     	 
     	 #都是随机选,整了一堆随机值放在列表里面
        t_num_l.append(randint(256, 65535))
        lucky_id_l.append(randint(0, 3))
        if i < 4:
            lucky_v_l.append(randint(1, 255))
            if lucky_per(15, 1):
                sym_mid_l.append(sym_str[randint(len(sym_str) - 1 - 3, len(sym_str) - 1)])
            else:
                sym_mid_l.append(sym_str[randint(2, len(sym_str) - 1 - 3)])

    result_list = []
    for i in range(4):
        equation_info = ''
        equation_info += '(0x%x %s 0x%x)' % (t_num_l[(i * 2 + 0)], sym_l[(i * 2 + 0)], lucky_v_l[lucky_id_l[(i * 2 + 0)]])
        equation_info += ' %s ' % sym_mid_l[i]
        equation_info += '(0x%x %s 0x%x)' % (t_num_l[(i * 2 + 1)], sym_l[(i * 2 + 1)], lucky_v_l[lucky_id_l[(i * 2 + 1)]])
        result_val = int(eval(equation_info)) & 4294967295
        result_list.append(result_val)

    lucky_num = '0x'
    for i in range(4):
        lucky_num += '%02x' % lucky_v_l[(3 - i)]

    TMP_NUM_LIST = ''
    U_V_LIST = ''
    SYM_LIST = ''
    SYM_MID_LIST = ''
    RESULT_LIST = ''
    for i in range(8):
        TMP_NUM_LIST += '#define TMP_NUM%d 0x%x\n' % (i, t_num_l[i])
        U_V_LIST += '#define U_V%d 0x%x\n' % (i, lucky_id_l[i])
        SYM_LIST += '#define SYM%d %c\n' % (i, sym_l[i])
        if i < 4:
            SYM_MID_LIST += '#define SYM_MID%d %c\n' % (i, sym_mid_l[i])
            RESULT_LIST += '#define RESULT%d 0x%x\n' % (i, result_list[i])
	 
	 #把原本C文件中的宏定义用随机出来的数字顶替掉,然后会用宏定义整出来函数
    STACK_SIZE = '#define STACK_SIZE 0x%x\n' % randint(16, 768)
    data = data.replace('#define TMP_NUM_LIST\n', TMP_NUM_LIST)
    data = data.replace('#define U_V_LIST\n', U_V_LIST)
    data = data.replace('#define SYM_LIST\n', SYM_LIST)
    data = data.replace('#define SYM_MID_LIST\n', SYM_MID_LIST)
    data = data.replace('#define RESULT_LIST\n', RESULT_LIST)
    data = data.replace('#define STACK_SIZE\n', STACK_SIZE)
    return data

#就是做了个输入转成int类型
def get_int(data):
    data = data.strip()
    try:
        if data.startswith('0x'):
            val = int(data, 16)
            return (
             val, True)
        else:
            val = int(data)
            return (val, True)

    except Exception as e:
        return (
         0, False)


from select import select
import sys
#就是输出
def sys_write(info):
    sys.stdout.write(info)
    sys.stdout.flush()


def do_work(name):
    try:
        target_name = gen_name(name)
        #就先把这target_name一顿随机
        dirname = '/tmp/aeg_yeah_dir'
        #给个目录
        prepare_dir(dirname)
        #建了个目录
        do_command('rm /tmp/aeg_yeah_dir/%s_*.*' % name)
        #不停的删除这个文件
        data = read_file('aeg_bin_model.c')
        #读这个C文件
        data = replace_info(data)
        #然后把C语言文件经过一顿加工处理
        #重点就是这个加工处理的过程
        write_file('/tmp/aeg_yeah_dir/%s.c' % target_name, data)
        #写到这个文件里面去
        do_command('./run_make.sh %s' % target_name)
        #执行
        #gcc -fno-stack-protector -o /tmp/aeg_yeah_dir/$1.bin /tmp/aeg_yeah_dir/$1.c
        # #rm /tmp/aeg_yeah_dir/$1.c #
        #strip /tmp/aeg_yeah_dir/$1.bin
        print '------------------data info------------------'
        data = read_file('/tmp/aeg_yeah_dir/%s.bin' % target_name)
        print data.encode('base64').replace('\n', '')
        sys_write("Hi, input code (run as './tmp.bin code') :")
        timeout = 20
        #然后数据输出来
        #时间限制是20
        
        rlist, _, _ = select([sys.stdin], [], [], timeout)
        if rlist:
            data = sys.stdin.readline()
            input_code, status = get_int(data)
            #状态时ture的话执行下面的命令
            if status == True:
                print do_command('./run_aeg_bin.sh %s %d' % (target_name, input_code))
                #命令的内容是
                #cd flag_dir
                #export LD_LIBRARY_PATH=./
                #/tmp/aeg_yeah_dir/$1.bin $2 2>/dev/null
                #意思就是执行那个文件,然后参数当然是我们的输入input_code
            else:
                print 'bad input'
        else:
            print 'timeout'
    
    except Exception as e:
        pass

    do_command('rm /tmp/aeg_yeah_dir/%s_*.*' % name)


import sys
if __name__ == '__main__':
    if len(sys.argv) != 1:
        print 'Usage: python run_aeg_yeah.py'
    else:
        print '----------Welcome to  GEG!!!----------'
        do_work(gen_rand_str(16))
        #调用do_work,参数是长度是16的随机字符串
#include <stdio.h>
#include <unistd.h>

#define MAX_BUF_SZIE 0x80

void init_io()
{
	setvbuf(stdin, 0, 2, 0);
	setvbuf(stdout, 0, 2, 0);
}

#define false 0
#define true 1

#define TMP_NUM_LIST
#define U_V_LIST
#define SYM_LIST
#define SYM_MID_LIST
#define RESULT_LIST

#define STACK_SIZE

#define EQUATION(v) (TMP_NUM##v SYM##v ptr[U_V##v])
#define CHECK(v0, v1, r) ((EQUATION(v0) SYM_MID##r EQUATION(v1)) == RESULT##r)
#define IF_FALSE(v0, v1, r) CHECK(v0, v1, r) == false
//三个宏定义,就是题目中的约束
//约束的内容就是IF_FALSE函数判断,里面调用CHECK,最后是调用EQUATION
//EQUATION就是构造一个表达式,然后最后等于一个式子,这就是我们要过的约束

int vul_func(int equ_num)
{
	//有漏洞的函数里面四个约束,然后来到栈溢出的地方
	//buf的长度也是随机值
	char buff[STACK_SIZE];
	unsigned char *ptr = (unsigned char *)&equ_num;
	if (IF_FALSE(0, 1, 0))
		goto equ_fail;
	if (IF_FALSE(2, 3, 1))
		goto equ_fail;
	if (IF_FALSE(4, 5, 2))
		goto equ_fail;
	if (IF_FALSE(6, 7, 3))
		goto equ_fail;
	read(0, buff, STACK_SIZE+MAX_BUF_SZIE*3);
	return 1;
equ_fail:
	return 0;
}

int main(int argc, char **argv)
{
	init_io();
	alarm(6);
	if (argc < 2)
		exit(0);
	return vul_func(atoi(argv[1]));
}

整体上还是那么回事,但是感觉写的有点麻烦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值