aboutsummaryrefslogtreecommitdiffstats
path: root/examples/complex/dns_spoofing.py
blob: 632783a7757ca4f929ad30763608ccf1dc38fca7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"""
This script makes it possible to use mitmproxy in scenarios where IP spoofing
has been used to redirect connections to mitmproxy. The way this works is that
we rely on either the TLS Server Name Indication (SNI) or the Host header of the
HTTP request. Of course, this is not foolproof - if an HTTPS connection comes
without SNI, we don't know the actual target and cannot construct a certificate
that looks valid. Similarly, if there's no Host header or a spoofed Host header,
we're out of luck as well. Using transparent mode is the better option most of
the time.

Usage:
    mitmproxy
        -p 443
        -s dns_spoofing.py
        # Used as the target location if neither SNI nor host header are present.
        -R http://example.com/
        # To avoid auto rewriting of host header by the reverse proxy target.
        --keep-host-header
    mitmdump
        -p 80
        -R http://localhost:443/

    (Setting up a single proxy instance and using iptables to redirect to it
    works as well)
"""
import re

# This regex extracts splits the host header into host and port.
# Handles the edge case of IPv6 addresses containing colons.
# https://bugzilla.mozilla.org/show_bug.cgi?id=45891
parse_host_header = re.compile(r"^(?P<host>[^:]+|\[.+\])(?::(?P<port>\d+))?$")


class Rerouter:
    def request(self, flow):
        if flow.client_conn.ssl_established:
            flow.request.scheme = "https"
            sni = flow.client_conn.connection.get_servername()
            port = 443
        else:
            flow.request.scheme = "http"
            sni = None
            port = 80

        host_header = flow.request.host_header
        m = parse_host_header.match(host_header)
        if m:
            host_header = m.group("host").strip("[]")
            if m.group("port"):
                port = int(m.group("port"))

        flow.request.host_header = host_header
        flow.request.host = sni or host_header
        flow.request.port = port


addons = [Rerouter()]
0; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 * LZMA compressed kernel decompressor for ADM5120 boards
 *
 * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
 * Copyright (C) 2007 OpenWrt.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 *
 * Please note, this was code based on the bunzip2 decompressor code
 * by Manuel Novoa III  (mjn3@codepoet.org), although the only thing left
 * is an idea and part of original vendor code
 *
 *
 * 12-Mar-2005  Mineharu Takahara <mtakahar@yahoo.com>
 *   pass actual output size to decoder (stream mode
 *   compressed input is not a requirement anymore)
 *
 * 24-Apr-2005 Oleg I. Vdovikin
 *   reordered functions using lds script, removed forward decl
 *
 * 24-Mar-2007 Gabor Juhos
 *   pass original values of the a0,a1,a2,a3 registers to the kernel
 *
 * 19-May-2007 Gabor Juhos
 *   endiannes related cleanups
 *   add support for decompressing an embedded kernel
 *
 */

#include <stddef.h>

#include "config.h"
#include "LzmaDecode.h"

#define ADM5120_FLASH_START	0x1fc00000	/* Flash start */
#define ADM5120_FLASH_END	0x1fe00000	/* Flash end */

#define KSEG0			0x80000000
#define KSEG1			0xa0000000

#define KSEG1ADDR(a)		((((unsigned)(a)) & 0x1fffffffU) | KSEG1)

#define Index_Invalidate_I	0x00
#define Index_Writeback_Inv_D   0x01

#define cache_unroll(base,op)	\
	__asm__ __volatile__(		\
		".set noreorder;\n"		\
		".set mips3;\n"			\
		"cache %1, (%0);\n"		\
		".set mips0;\n"			\
		".set reorder\n"		\
		:				\
		: "r" (base),			\
		  "i" (op));

static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
{
	unsigned long start = KSEG0;
	unsigned long end = (start + size);

	while(start < end) {
		cache_unroll(start,Index_Invalidate_I);
		start += lsize;
	}
}

static __inline__ void blast_dcache(unsigned long size, unsigned long lsize)
{
	unsigned long start = KSEG0;
	unsigned long end = (start + size);

	while(start < end) {
		cache_unroll(start,Index_Writeback_Inv_D);
		start += lsize;
	}
}

#define TRX_MAGIC       0x30524448      /* "HDR0" */
#define TRX_ALIGN	0x1000

struct trx_header {
	unsigned int magic;		/* "HDR0" */
	unsigned int len;		/* Length of file including header */
	unsigned int crc32;		/* 32-bit CRC from flag_version to end of file */
	unsigned int flag_version;	/* 0:15 flags, 16:31 version */
	unsigned int offsets[3];	/* Offsets of partitions from start of header */
};

/* beyound the image end, size not known in advance */
extern unsigned char workspace[];
#if LZMA_WRAPPER
extern unsigned char _lzma_data_start[];
extern unsigned char _lzma_data_end[];
#endif

extern void board_init(void);
extern void board_putc(int ch);

struct env_var {
	char	*name;
	char	*value;
};

#ifdef CONFIG_PASS_KARGS
#define ENVV(n,v)	{.name = (n), .value = (v)}
struct env_var env_vars[] = {
	ENVV("board_name",	CONFIG_BOARD_NAME),
	ENVV(NULL, NULL)
};
#endif

unsigned char *data;
unsigned long datalen;

typedef void (*kernel_entry)(unsigned long reg_a0, unsigned long reg_a1,
	unsigned long reg_a2, unsigned long reg_a3);

static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
{
	*bufferSize = 1;
	*buffer = data++;

	return LZMA_RESULT_OK;
}

static __inline__ unsigned char get_byte(void)
{
	unsigned char *buffer;
	UInt32 fake;

	read_byte(0, &buffer, &fake);
	return *buffer;
}

static __inline__ unsigned int read_le32(void *buf)
{
	unsigned char *p;

	p = buf;
	return ((unsigned int)p[0] + ((unsigned int)p[1] << 8) +
		((unsigned int)p[2] << 16) +((unsigned int)p[3] << 24));
}

static void print_char(char ch)
{
	if (ch == '\n')
		board_putc('\r');
    	board_putc(ch);
}

static void print_str(char * str)
{
	while ( *str != 0 )
    		print_char(*str++);
}

static void print_hex(int val)
{
	int i;
	int tmp;

	print_str("0x");
	for ( i=0 ; i<8 ; i++ ) {
    		tmp = (val >> ((7-i) * 4 )) & 0xf;
    		tmp = tmp < 10 ? (tmp + '0') : (tmp + 'A' - 10);
    		board_putc(tmp);
	}
}

#if !(LZMA_WRAPPER)
static unsigned char *find_kernel(void)
{
	struct trx_header *hdr;
	unsigned char *ret;

    	print_str("Looking for TRX header... ");
	/* look for trx header, 32-bit data access */
	hdr = NULL;
	for (ret = ((unsigned char *) KSEG1ADDR(ADM5120_FLASH_START));
		ret < ((unsigned char *)KSEG1ADDR(ADM5120_FLASH_END));
		ret += TRX_ALIGN) {

		if (read_le32(ret) == TRX_MAGIC) {
			hdr = (struct trx_header *)ret;
			break;
		}
	}

	if (hdr == NULL) {
		print_str("not found!\n");
		return NULL;
	}

	print_str("found at ");
	print_hex((unsigned int)ret);
	print_str(", kernel in partition ");

	/* compressed kernel is in the partition 0 or 1 */
	if ((read_le32(&hdr->offsets[1]) == 0) ||
		(read_le32(&hdr->offsets[1]) > 65536)) {
		ret += read_le32(&hdr->offsets[0]);
		print_str("0\n");
	} else {
		ret += read_le32(&hdr->offsets[1]);
		print_str("1\n");
	}

	return ret;
}
#endif /* !(LZMA_WRAPPER) */

static void halt(void)
{
	print_str("\nSystem halted!\n");
	for(;;);
}

/* should be the first function */
void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
	unsigned long reg_a2, unsigned long reg_a3,
	unsigned long icache_size, unsigned long icache_lsize,
	unsigned long dcache_size, unsigned long dcache_lsize)
{
	unsigned int i;  /* temp value */
	unsigned int lc; /* literal context bits */
	unsigned int lp; /* literal pos state bits */
	unsigned int pb; /* pos state bits */
	unsigned int osize; /* uncompressed size */
	int res;
#if !(LZMA_WRAPPER)
	ILzmaInCallback callback;
#endif

	board_init();

	print_str("\n\nLZMA loader for " CONFIG_BOARD_NAME
			", Copyright (C) 2007 OpenWrt.org\n\n");

#if LZMA_WRAPPER
	data = _lzma_data_start;
	datalen = _lzma_data_end - _lzma_data_start;
#else
	data = find_kernel();
	if (data == NULL) {
		/* no compressed kernel found, halting */
		halt();
	}

	datalen = ((unsigned char *) KSEG1ADDR(ADM5120_FLASH_END))-data;
#endif

	/* lzma args */
	i = get_byte();
	lc = i % 9, i = i / 9;
	lp = i % 5, pb = i / 5;

	/* skip rest of the LZMA coder property */
	for (i = 0; i < 4; i++)
		get_byte();

	/* read the lower half of uncompressed size in the header */
	osize = ((unsigned int)get_byte()) +
		((unsigned int)get_byte() << 8) +
		((unsigned int)get_byte() << 16) +
		((unsigned int)get_byte() << 24);

	/* skip rest of the header (upper half of uncompressed size) */
	for (i = 0; i < 4; i++)
		get_byte();

	print_str("decompressing kernel... ");

	/* decompress kernel */
#if LZMA_WRAPPER
	res = LzmaDecode(workspace, ~0, lc, lp, pb, data, datalen,
		(unsigned char*)LOADADDR, osize, &i);
#else
	callback.Read = read_byte;
	res = LzmaDecode(workspace, ~0, lc, lp, pb, &callback,
		(unsigned char*)LOADADDR, osize, &i);
#endif
	if (res != LZMA_RESULT_OK) {
		print_str("failed!\n");
		print_str("LzmaDecode: ");
		switch (res) {
		case LZMA_RESULT_DATA_ERROR:
			print_str("data error\n");
			break;
		case LZMA_RESULT_NOT_ENOUGH_MEM:
			print_str("not enough memory\n");
			break;
		default:
			print_str("unknown error, err=0x");
			print_hex(res);
			print_str("\n");
		}
		halt();
	}

        print_str("done!\n");

	blast_dcache(dcache_size, dcache_lsize);
	blast_icache(icache_size, icache_lsize);

	print_str("launching kernel...\n\n");

#ifdef CONFIG_PASS_KARGS
	reg_a0 = 0;
	reg_a1 = 0;
	reg_a2 = (unsigned long)env_vars;
	reg_a3 = 0;
#endif
	/* Jump to load address */
	((kernel_entry) LOADADDR)(reg_a0, reg_a1, reg_a2, reg_a3);
}