Inject code into process in ubuntu 64bit - linux

I'm learning ptrace by the article "playing with ptrace".
Now I can set breakpoint by replacing tracee's instruction with "syscall" but can't inject code successfully.
In X86 , the print can use "int 80" then pause process by "int3".
How can I inject code that has instruction "syscall " and stop process when the inject code finish in x64 Thanks.
The code I inject is this
section .text
global main
main:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, 13
syscall
int3
message:
db "Hello world", 10
My code is
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LONG_SIZE 8
void getdata(pid_t child, long addr,char *str,int len)
{
char *laddr = str;
int i = 0,j = len/LONG_SIZE;
union u{
long val;
char chars[LONG_SIZE];
} word;
while(i<j)
{
word.val = ptrace(PTRACE_PEEKDATA,child,addr + i*LONG_SIZE,NULL);
if(word.val == -1)
perror("trace error");
memcpy(laddr,word.chars,LONG_SIZE);
++i;
laddr += LONG_SIZE;
}
j = len %LONG_SIZE;
if(j!=0)
{
word.val == ptrace(PTRACE_PEEKDATA,child,addr + i*LONG_SIZE,NULL);
if(word.val == -1)
perror("trace error");
}
str[len] = '\0';
}
void putdata(pid_t child,long addr,char *str,int len)
{
char *laddr = str;
int i = 0, j = len/LONG_SIZE;
union u{
long val;
char chars[LONG_SIZE];
}word;
while(i<j)
{
memcpy(word.chars,laddr,LONG_SIZE);
if(ptrace(PTRACE_POKEDATA,child,addr+i*LONG_SIZE,word.val) == -1)
perror("trace error");
++i;
laddr += LONG_SIZE;
}
j = len % LONG_SIZE;
if(j != 0)
{
word.val = 0;
memcpy(word.chars,laddr,j);
if(ptrace(PTRACE_POKEDATA,child,addr+i*LONG_SIZE,word.val) == -1)
perror("trace error");
}
}
void printBytes(const char* tip,char* codes,int len)
{
int i;
printf("%s :",tip);
for(i = 0;i<len;++i)
{
printf("%02x ",(unsigned char)codes[i]);
}
puts("");
}
#define CODE_SIZE 48
int main(int argc ,char *argv[])
{
if(argc != 2)
{
puts("no pid input");
exit(1);
}
pid_t traced_process;
struct user_regs_struct regs;
long ins;
char code[CODE_SIZE] = {0xb8,0x01,0x00,0x00,0x00,0xbf,0x01,0x00,0x00,0x00,0x48,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xba,0x0d,0x00,0x00,0x00,0x0f,0x05,0xcc,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x77,0x6f,0x72,0x6c,0x64,0x0a};
char backup[CODE_SIZE];
traced_process = atoi(argv[1]);
printf("try to attach pid:%u\n",traced_process);
if(ptrace(PTRACE_ATTACH,traced_process,NULL,NULL) == -1)
{
perror("trace attach error");
}
wait(NULL);
if(ptrace(PTRACE_GETREGS,traced_process,NULL,&regs) == -1)
{
perror("trace get regs error");
}
//copy instructions into backup variable
getdata(traced_process,regs.rip,backup,CODE_SIZE);
printBytes("get tracee instuction",backup,CODE_SIZE);
puts("try to inject code");
putdata(traced_process,regs.rip,code,CODE_SIZE);
puts("inject success, tracee continue");
if(ptrace(PTRACE_CONT,traced_process,NULL,NULL) == -1)
{
perror("trace continue error");
}
//wait tracee to execute int3 to stop
wait(NULL);
puts("inject code finish, Press <Enter> to continue");
getchar();
printBytes("place inject instructions with backup instructions",backup,CODE_SIZE);
putdata(traced_process,regs.rip,backup,CODE_SIZE);
ptrace(PTRACE_SETREGS,traced_process,NULL,&regs);
ptrace(PTRACE_DETACH,traced_process,NULL,NULL);
return 0;
}
It doesn't work, only can make tracee stop and resume. what's wrong with it?
run it in ubuntu 16.04 64bit.

You said it yourself. Use a command that raises a signal.
Debuggers use int 3, for a very simple reason. While every single software interrupt you raise is a couple of bytes long (one for the int command, and another for the interrupt number), int 3 is a single byte instruction. It is that precisely so it can be easily injected (and then removed) by a debugger.
To summarize, since you are on x86_64, replace the int 80 injection with syscall, but leave the other software interrupt as they were.

I know the reason. the asm code that I post is not PIC, when it is injected into tracee's memory, string address is wrong, so it failed.
right asm code should be
section .text
global main
main:
jmp forward
backward:
pop rsi
mov rax, 1
mov rdi, 1
mov rdx, 13
syscall
int3
forward:
call backward
db "Hello world",0xa

Related

How to delete/release a named semaphore from linux command prompt?

I have a code as under.It crashes when accessing the semaphore and I have created "named semaphores" that I am unable to delete from command prompt after the crash. How can I delete them using a command prompt utility? The code is trying to create Rock,Paper,Scissors game that can be run from 2 producer(player) command prompts and one consumer (result) command prompt. I would also appreciate suggestions to fix/correct/improve the code.
//compiled by executing --> gcc -pthread logic.c -lrt
#include <stdio.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
//don't need an exec call just based on paramters run the processes
typedef struct sync_tools
{
int pid;
void* shm_ptr;
sem_t* sem_array[2];
} sync_tools;
void producer(void * ctx)
{
char choice;
sync_tools *ctxt=(sync_tools*)ctx;
while(1)
{
printf ("Enter the following for input \n");
printf ("R. Rock\n");
printf ("P. Paper\n");
printf ("S. Scissors\n");
scanf ("%c",&choice);
if (ctxt->pid==1)
{
printf ("Process1\n");
sem_wait(ctxt->sem_array[0]);
sprintf((char*) ctxt->shm_ptr, "%c\n", choice);
sem_post(ctxt->sem_array[0]);
printf ("Process1\n");
}
else
{
printf ("Process2\n");
sem_wait(ctxt->sem_array[1]);
sprintf((char*) (ctxt->shm_ptr+1), "%c\n", choice);
sem_post(ctxt->sem_array[1]);
}
}
}
//need 2 semphores for sync
void consumer(void *ctx)
{
sync_tools *ctxt=(sync_tools*)ctx;
char data[2]={0x00};
int flag=1;
while(1)
{
sem_wait(ctxt->sem_array[0]);
sem_wait(ctxt->sem_array[1]);
scanf ((char *) ctxt->shm_ptr, "%c", &data[0]);
scanf ((char *) (ctxt->shm_ptr+1), "%c", &data[1]);
switch(data[0])
{
case 'R':
case 'r':
if ((data[1] =='p')|| (data[1]=='P'));
flag=0;
break;
case'P':
case'p':
if ((data[1] =='s')|| (data[1]=='S'));
flag=0;
break;
case 's':
case'S':
if ((data[1] =='R')|| (data[1]=='R'));
flag=0;
break;
}
if (flag)
printf("Process 1 wins \n");
else
printf("Process 2 wins \n");
sem_post(ctxt->sem_array[0]);
sem_post(ctxt->sem_array[1]);
}
}
int main (int argc, char* argv[])
{
char choice;
int SIZE=4096;
char *name="SHM_WQ";
sync_tools cntxt={}; //initialize without memset
//calling sem_open as I want a named semaphore which is not locally available by copy like in forked processes.
cntxt.sem_array[0]= sem_open ("P1C", O_CREAT | O_EXCL, 0644, 1);
cntxt.sem_array[1]= sem_open ("P2C", O_CREAT | O_EXCL, 0644, 1);
/* shared memory file descriptor */
int shm_fd;
/* pointer to shared memory object */
void* ptr;
/* create the shared memory object */
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory object */
ftruncate(shm_fd, SIZE);
/* memory map the shared memory object */
ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0); //sys/mman.h
cntxt.shm_ptr=ptr;
//pass the shared memory and semaphores to all the threads and spawn them
if(strcmp(argv[1], "p1") == 0)
cntxt.pid=1;
else if (strcmp(argv[1], "p2") ==0)
cntxt.pid=2;
else if (strcmp(argv[1], "c") ==0)
cntxt.pid=3;//don't care
producer(&cntxt);
consumer(&cntxt);
}
Modified my code as under:
cntxt.sem_array[0] = sem_open("P1C", 0);
cntxt.sem_array[1] = sem_open("P2C", 0);
if (cntxt.sem_array[0] == NULL)
{
cntxt.sem_array[0]= sem_open ("P1C", O_CREAT | O_EXCL, 0644, 2);
}
if (cntxt.sem_array[1] == NULL)
{
cntxt.sem_array[1]= sem_open ("P2C", O_CREAT | O_EXCL, 0644, 2);
}
if ((cntxt.sem_array[0] == NULL) || (cntxt.sem_array[1] == NULL))
printf("SEM_OPEN ERROR");
Also as mentioned in the comment, created a small utility that takes semname and unlinks it from kernel.

Linux simulate write() system call failure using ptrace()

I am trying to simulate failure of write() system call.
I have read that return value -1 (in EAX) indicates error in system call and errno gives the exact reason for failure.
I am trying to intercept system call write() return -1 in EAX register and set the "errno" to some error value.
puts() internally uses write(), which is system call number 4.
If i do perror("Error:") in the child, it should show the error corresponding to "errno" which i would like to set.
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/reg.h> /* For constants ORIG_EAX etc */
#include <stdio.h>
#include <sys/user.h>
#include <errno.h>
int main()
{ pid_t child;
int status;
long orig_eax,eax,params[3];
int ret_val=-1,insyscall=0;
struct user_regs_struct regs;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/home/kashi/Documents/2nd_Sem/MyPrgms/ptrace/ramana/write", "write", NULL);
//execl("/bin/ls","ls",NULL);
}
else {
while(1)
{
wait(&status);
if(WIFEXITED(status))
break;
orig_eax = ptrace(PTRACE_PEEKUSER,
child, 4 * ORIG_EAX, NULL);
if(orig_eax == 4)
{
ptrace( PTRACE_GETREGS, child, 0, &regs );
printf("Write called with %ld, %ld %ld\n",regs.ebx, regs.ecx,regs.edx);
if(insyscall == 0)
{
/* Syscall entry */
printf("In %d\n",insyscall);
insyscall = 1;
}
else
{
/* Syscall exit */
regs.orig_eax=-1;
**errno=11; //This errno should be set in the child process, how to do it?**
ptrace( PTRACE_SETREGS, child, 0, &regs );
eax = ptrace(PTRACE_PEEKUSER, child, 4 * ORIG_EAX, NULL);
printf("Write returned with %ld\n", eax);
insyscall = 0;
}
}
//printf("The child made a "
// "system call %ld\n", regs.orig_eax);
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
}
}
return 0;
}
The tracee program (testwrite.c) is:
#include<stdio.h>
#include<unistd.h>
#include<sys/ptrace.h>
#include<signal.h>
#include<errno.h>
//int display(char *p);
int main()
{
printf("Hi Kashi\n");
perror("Error: ");
return 0;
}
output:
[kashi#localhost ramana]$ ./test.sh
In 0
Hi Kashi
Write returned with -1
In 0
**Error: : Success**
Write returned with -1
The perror("Error:") displays text message corresponding to "errno". I am not able to set this "errno" in child process, how can i do it?

I2C_SLAVE ioctl purpose

I am writing code for implementing a simple i2c read/write function using the general linux i2c driver linux/i2c-dev.h
I am confused about the ioctl : I2C_SLAVE
The kernel documentation states as follows :
You can do plain i2c transactions by using read(2) and write(2) calls.
You do not need to pass the address byte; instead, set it through
ioctl I2C_SLAVE before you try to access the device
However I am using the ioctl I2C_RDWR where I again set the slave address using i2c_msg.addr.
The kernel documentation also mentions the following :
Some ioctl() calls are for administrative tasks and are handled by
i2c-dev directly. Examples include I2C_SLAVE
So is it must to use the ioctl I2C_SLAVE? If so do I need to set it just once or every time I perform a read and write?
If I had an i2c device I could have just tested the code on the device and would not have bothered you guys but unfortunately I don't have one right now.
Thanks for the help.
There are three major methods of communicating with i2c devices from userspace.
1. IOCTL I2C_RDWR
This method allows for simultaneous read/write and sending an uninterrupted sequence of message. Not all i2c devices support this method.
Before performing i/o with this method, you should check whether the device supports this method using an ioctl I2C_FUNCS operation.
Using this method, you do not need to perform an ioctl I2C_SLAVE operation -- it is done behind the scenes using the information embedded in the messages.
2. IOCTL SMBUS
This method of i/o is more powerful but the resulting code is more verbose. This method can be used if the device does not support the I2C_RDWR method.
Using this method, you do need to perform an ioctl I2C_SLAVE operation (or, if the device is busy, an I2C_SLAVE_FORCE operation).
3. SYSFS I/O
This method uses the basic file i/o system calls read() and write(). Uninterrupted sequential operations are not possible using this method. This method can be used if the device does not support the I2C_RDWR method.
Using this method, you do need to perform an ioctl I2C_SLAVE operation (or, if the device is busy, an I2C_SLAVE_FORCE operation).
I can't think of any situation when this method would be preferable to others, unless you need the chip to be treated like a file.
Full IOCTL Example
I haven't tested this example, but it shows the conceptual flow of writing to an i2c device.-- automatically detecting whether to use the ioctl I2C_RDWR or smbus technique.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#define I2C_ADAPTER "/dev/i2c-0"
#define I2C_DEVICE 0x00
int i2c_ioctl_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data, size_t size)
{
int i, j = 0;
int ret;
uint8_t *buf;
// the extra byte is for the regaddr
size_t buff_size = 1 + size;
buf = malloc(buff_size);
if (buf == NULL) {
return -ENOMEM;
}
buf[j ++] = regaddr;
for (i = 0; i < size / sizeof(uint16_t); i ++) {
buf[j ++] = (data[i] & 0xff00) >> 8;
buf[j ++] = data[i] & 0xff;
}
struct i2c_msg messages[] = {
{
.addr = dev,
.buf = buf,
.len = buff_size,
},
};
struct i2c_rdwr_ioctl_data payload = {
.msgs = messages,
.nmsgs = sizeof(messages) / sizeof(messages[0]),
};
ret = ioctl(fd, I2C_RDWR, &payload);
if (ret < 0) {
ret = -errno;
}
free (buf);
return ret;
}
int i2c_ioctl_smbus_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data, size_t size)
{
int i, j = 0;
int ret;
uint8_t *buf;
buf = malloc(size);
if (buf == NULL) {
return -ENOMEM;
}
for (i = 0; i < size / sizeof(uint16_t); i ++) {
buf[j ++] = (data[i] & 0xff00) >> 8;
buf[j ++] = data[i] & 0xff;
}
struct i2c_smbus_ioctl_data payload = {
.read_write = I2C_SMBUS_WRITE,
.size = I2C_SMBUS_WORD_DATA,
.command = regaddr,
.data = (void *) buf,
};
ret = ioctl (fd, I2C_SLAVE_FORCE, dev);
if (ret < 0)
{
ret = -errno;
goto exit;
}
ret = ioctl (fd, I2C_SMBUS, &payload);
if (ret < 0)
{
ret = -errno;
goto exit;
}
exit:
free(buf);
return ret;
}
int i2c_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data, size_t size)
{
unsigned long funcs;
if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
return -errno;
}
if (funcs & I2C_FUNC_I2C) {
return i2c_ioctl_write (fd, dev, regaddr, data, size);
} else if (funcs & I2C_FUNC_SMBUS_WORD_DATA) {
return i2c_ioctl_smbus_write (fd, dev, regaddr, data, size);
} else {
return -ENOSYS;
}
}
int parse_args (uint8_t *regaddr, uint16_t *data, size_t size, char *argv[])
{
char *endptr;
int i;
*regaddr = (uint8_t) strtol(argv[1], &endptr, 0);
if (errno || endptr == argv[1]) {
return -1;
}
for (i = 0; i < size / sizeof(uint16_t); i ++) {
data[i] = (uint16_t) strtol(argv[i + 2], &endptr, 0);
if (errno || endptr == argv[i + 2]) {
return -1;
}
}
return 0;
}
void usage (int argc, char *argv[])
{
fprintf(stderr, "Usage: %s regaddr data [data]*\n", argv[0]);
fprintf(stderr, " regaddr The 8-bit register address to write to.\n");
fprintf(stderr, " data The 16-bit data to be written.\n");
exit(-1);
}
int main (int argc, char *argv[])
{
uint8_t regaddr;
uint16_t *data;
size_t size;
int fd;
int ret = 0;
if (argc < 3) {
usage(argc, argv);
}
size = (argc - 2) * sizeof(uint16_t);
data = malloc(size);
if (data == NULL) {
fprintf (stderr, "%s.\n", strerror(ENOMEM));
return -ENOMEM;
}
if (parse_args(&regaddr, data, size, argv) != 0) {
free(data);
usage(argc, argv);
}
fd = open(I2C_ADAPTER, O_RDWR | O_NONBLOCK);
ret = i2c_write(fd, I2C_DEVICE, regaddr, data);
close(fd);
if (ret) {
fprintf (stderr, "%s.\n", strerror(-ret));
}
free(data);
return ret;
}
If you use the read() and write() methods, calling ioctl with I2C_SLAVE once is enough. You can also use I2C_SLAVE_FORCE if the device is already in use.
However I haven't yet found a consistent way to read specific registers for every device using the read()/write() methods.
I'm not too sure if this helps because I don't use ioctl I2C_RDWR but I've been using the following code with success:
int fd;
fd = open("/dev/i2c-5", O_RDWR);
ioctl(fd, I2C_SLAVE_FORCE, 0x20);
i2c_smbus_write_word_data(fd, ___, ___);
i2c_smbus_read_word_data(fd, ___);
All I do is set I2C_SLAVE_FORCE once at the beginning and I can read and write as much as I want to after that.
PS - This is just a code sample and obviously you should check the returns of all of these functions. I'm using this code to communicate with a digital I/O chip. The two i2c_* functions are just wrappers that call ioctl(fd, I2C_SMBUS, &args); where args is a struct i2c_smbus_ioctl_data type.
For the interested, SLAVE_FORCE is used when the device in question is already being managed by a kernel driver. (i2cdetect will show UU for that address)

Backtracing on Linux 64 bit from Signal Handler with malloc/free on callstack

Below is an example of source I want to use on a machine running "Red Hat Enterprise Linux 5.5 (Tikanga) Kernel 2.6.18-194.el5xen x86_64" OS.
The general idea is that I want to have backtrace of some thread, so I am raising a SIGUSR1 signal for that thread and a handler does a backtrace() call.
In my scenario as below, FrameTwo function calls malloc and free in a loop. Whenever the signal is raised for this particular thread and free or malloc is on the callstack, the progream crashes when the signal handler calls backtrace().
(gdb) where (stack from gdb)
0 0x0000003e67207638 in ?? ()
1 0x0000003e672088bb in _Unwind_Backtrace
2 0x00000037ba0e5fa8 in backtrace ()
3 0x000000000040071a in handler ()
4 <signal handler called>
5 0x00000037ba071fac in _int_free ()
6 0x0000000a33605000 in ?? ()
7 0x000000004123b130 in ?? ()
8 0x00000000004007d4 in ThreadFunction ()
9 0x000000001f039020 in ?? ()
10 0x000000004123b940 in ?? ()
11 0x0000000000000001 in ?? ()
12 0x0000000000000000 in ?? ()
I learned from other sources that backtrace shouldn't be called from a signal handler, so I have written my own function grok_and_print_thread_stack() for this case.
It uses the RBP register to navigate the stack (RBP contains the base pointer of the current frame points to the previous frame's base pointer), but this algorithm does not work in this case either: when _int_free () is on the callstack, the RBP register navigation algorithm breaks, because the RBP of _int_free is some value like 0x20 which is not a valid frame's base pointer.
Does anyone know how a callstack can be navigated from the registers? Or how can I use backtrace for my purpose?
#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
#include "signal.h"
#include "syscall.h"
#include "string.h"
#include "inttypes.h"
//####################################################################
//gcc BacktraceTestProgram.c -o backtracetest -lpthread
//./backtracetest
//gdb -c core backtracetest
//####################################################################
volatile sig_atomic_t flag = 1;
int thlist[6] = {0};
int cnt = 0;
int *memory = NULL;
//####################################################################
void raiseUserSignal(int tid)
{
union sigval value;
value.sival_int = 1;
sigqueue(tid,SIGUSR1, value);
}
//####################################################################
int grok_and_print_thread_stack()
{
int ret = 0;
register uint64_t* rbp asm("rbp");
/*if buffer was built before, add separator */
uint64_t *previous_bp;
/*save pointers*/
previous_bp = rbp;
/* stack Traversal */
while(previous_bp)
{
uint64_t *next_bp;
next_bp = (uint64_t*)*previous_bp;
printf("Read BP: %lx \n", next_bp);
if ( NULL == (void*)next_bp )
{
printf("Reached the top of the stack\n");
fflush(stdout);
break;
}
previous_bp = next_bp;
}
return ret;
}
//####################################################################
void handler(int signum, siginfo_t *info, void *context)
{
int nptrs = 0 ;
void *buffer[100] = {NULL};
char **strings = NULL;
nptrs = backtrace(buffer, 100);
flag = 1;
}
//####################################################################
void FrameTwo(const char A)
{
do{
if( memory == NULL)
memory = (int *)malloc(sizeof(int) *5);
if(memory != NULL) {
free(memory);
memory = NULL;
}
}while(1);
}
//####################################################################
void FrameOne(int no)
{
FrameTwo('A');
}
//####################################################################
void *ThreadFunction( void *ptr )
{
int tid = syscall(SYS_gettid);
thlist[cnt++] = tid;
FrameOne(10);
}
//####################################################################
void RegisterSignalHandler()
{
/* Register a Signal Handler */
struct sigaction usrsig_action;
usrsig_action.sa_flags = SA_SIGINFO;
usrsig_action.sa_sigaction = &handler;
sigaction (SIGUSR1, &usrsig_action, NULL);
}
//####################################################################
int main(int no , char *argc[] )
{
int iret1;
pthread_t thread1;
RegisterSignalHandler();
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, ThreadFunction, NULL);
while(cnt == 0);
while(1) {
if(flag == 1){
flag = 0;
raiseUserSignal(thlist[0]);
}
}
pthread_join( thread1, NULL);
return 0;
}
In general x86_64 programs are likely to have been built with -fomit-frame-pointer as it is the default when optimisation is on.
What that means is that RBP is not usable for unwinding the stack and you will either need to use the DWARF unwind information (if you have debugging information available) or the exception unwind table.
You may want to look at the libunwind project.
The primary goal of [libunwind] is to define a portable and efficient C programming interface (API) to determine the call-chain of a program. [...] As such, the API is useful in a number of applications. Some examples include:
debuggers
The libunwind API makes it trivial for debuggers to generate the call-chain (backtrace) of the threads in a running program/
In particular, have a look at the local unwinding section of their documentation, it contains explanations and the following code example (with you need to link with -lunwind) that prints the backtrace of the current function:
#define UNW_LOCAL_ONLY
#include <libunwind.h>
void show_backtrace (void) {
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
printf ("ip = %lx, sp = %lx\n", (long) ip, (long) sp);
}
}

ptrace attach to vsftpd hangs

I am trying to ptrace a vsftpd server process on linux to be able to get control whenever vsftpd process makes a system call. I start the vsftpd process and pass this process id as command line to the following program which traces vsftpd.
however, when I run the following program it just hangs and does not print anything.Can anyone point out what could be wrong? Thanks a lot for your help!!
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h>
#include <sys/syscall.h> /* For SYS_write etc */
#include<sys/reg.h>
int main(int argc,char* argv[])
{ pid_t child;
long orig_eax, eax;
long params[3];
int status;
int insyscall = 0;
child = atoi(argv[1]);
ptrace(PTRACE_ATTACH,child,NULL,NULL);
while(1) {
wait(&status);
if(WIFEXITED(status))
break;
orig_eax = ptrace(PTRACE_PEEKUSER,
child, 4 * ORIG_EAX, NULL);
if(orig_eax == __NR_clone || orig_eax == __NR_open || orig_eax == __NR_write)
{
if(insyscall == 0) {
/* Syscall entry */
insyscall = 1;
params[0] = ptrace(PTRACE_PEEKUSER,
child, 4 * EBX,
NULL);
params[1] = ptrace(PTRACE_PEEKUSER,
child, 4 * ECX,
NULL);
params[2] = ptrace(PTRACE_PEEKUSER,
child, 4 * EDX,
NULL);
if(orig_eax == __NR_clone)
{
printf("\nClone");
}
else if(orig_eax == __NR_open)
printf("\nOpen");
else if(orig_eax == __NR_write)
printf("\nWrite");
printf(" called with "
"%ld, %ld, %ld\n",
params[0], params[1],
params[2]);
}
else { /* Syscall exit */
eax = ptrace(PTRACE_PEEKUSER,
child, 4 * EAX, NULL);
printf("Returned "
"with %ld\n", eax);
insyscall = 0;
}
}
ptrace(PTRACE_SYSCALL,
child, NULL, NULL);
}
return 0;
}
You need to have the privilege to trace VSFTPD. Run this as root. To test, put the result of ptrace(PTRACE_ATTACH,child,NULL,NULL); into a variable and print it, ie.
long result = ptrace(PTRACE_ATTACH,child,NULL,NULL);
printf("%ld",result);
On my system if result == -1, I do not have permission. If result == 0, I do.

Resources