文件准备
首先看一段程序
# a.c > a.exe
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2){
return 1;
}
FILE *f = fopen(argv[1], "rb");
if (f == NULL) {
return 2;
}
int w, h;
fread(&w, 4, 1, f);
fread(&h, 4, 1, f);
unsigned char *buf = malloc(w * h);
for(int j=0; j<h ; j++){
fread(&buf[j * w], w, 1, f);
}
fclose(f);
return 0;
}
/*
# gcc 编译成32位的
gcc -m32 ./example.c ggdb
# 写测试文件
>>> import struct
>>> open("input.sample", "wb").write(struct.pack("II", 0xa, 0xa))
>>> open("input.sample", "ab").write(("A" * 10*10).encode("ascii"))
# 使用gdb调试
*/
编译后ida看无异
gdb 编译之后拖进ida看下有无优化
写python代码来随机输入
# https://www.youtube.com/watch?v=iTFmLJ4zn-E 42:09
# example.py
import subprocess
import random
import struct
import sys
import time
def load_file(fname):
with open(fname, "rb") as f:
return bytearray(f.read())
def save_file(fname, data):
with open(fname, "wb") as f:
f.write(str(data))
def mutate_bits(data):
data = data[::] # copy
count = int((len(data) * 8) * 0.01)
if count == 0:
count = 1
for _ in range(count):
bit = random.randint(0, len(data)*8 -1 )
idx_bit = bit % 8
idx_byte = bit / 8
data[idx_byte] ^= 1 << idx_bit
return data
def mutate_bytes(data):
count = int((len(data)) * 0.01)
if count == 0:
count = 1
for _ in range(count):
data[random.randint(0, len(data) - 1)] = random.randint(0, 255);
return data
def mutate_magic(data):
numbers = [
(1, struct.pack("B", 0xff)), # malloc((unsigned char)(text_length + 1))
(1, struct.pack("B", 0x7f)),
(1, struct.pack("B", 0)),
(2, struct.pack("H", 0xffff)),
(2, struct.pack("H", 0)),
(4, struct.pack("I", 0xffffffff)),
(4, struct.pack("I", 0)),
(4, struct.pack("I", 0x80000000)), # INT_MIN / -1
(4, struct.pack("I", 0x40000000)),
(4, struct.pack("I", 0x7fffffff)),
]
count = int(len(data) * 0.01)
if count == 0:
count = 1
for _ in range(count):
n_size, n = random.choice(numbers)
sz = len(data) - n_size
if sz < 0:
continue
idx = random.randint(0, sz)
data[idx:idx + n_size] = bytearray(n)
return data
def mutate(data):
return random.choice([
mutate_bits,
mutate_bytes,
mutate_magic
])(data[::])
def run(execname):
subprocess.check_call([execname, "test.sample"])
input_samples = [
load_file("input.sample")
# , "zzzz"
]
# print(random.choice(input_samples))
# output:
# like this:
# bytearray(b'\n\x00\x00\x00\n\x00\x00\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')
# or:
# zzzz
i = 0
while True:
i += 1
if True: # How many random produce one
sys.stdout.write(".")
sys.stdout.flush()
mutated_sample = mutate( random.choice(input_samples) )
save_file("test.sample", mutated_sample)
try:
run("a.exe") # produce this one
except subprocess.CalledProcessError:
print "CRASH!"
save_file("crash.samples.%i"%i , mutated_sample) # when CRASH then save input file
执行 > python example.py
右边是随机生成出来的数据, 左边是我们的元数据(通过a.c里面的命令生成的正常数据)
0000000a * 4000000a 很明显他会溢出