(75) Hacking Livestream #17 Basics of fuzzing 1 - YouTube (在寫..)

【帶機翻字幕】

文件準備

首先看一段程序

# 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 很明顯他會溢出

修改代碼, 用gdb script附加

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章