Playing with ptrace 2Word格式文档下载.docx
《Playing with ptrace 2Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《Playing with ptrace 2Word格式文档下载.docx(16页珍藏版)》请在冰点文库上搜索。
#include<
sys/ptrace.h>
sys/types.h>
sys/wait.h>
unistd.h>
linux/user.h>
/*Foruser_regs_struct
etc.*/
intmain(intargc,char*argv[])
{pid_ttraced_process;
structuser_regs_structregs;
longins;
if(argc!
=2){
Usage:
%s<
pidtobetraced>
\n"
argv[0],argv[1]);
exit
(1);
traced_process=atoi(argv[1]);
ptrace(PTRACE_ATTACH,traced_process,
NULL,NULL);
wait(NULL);
ptrace(PTRACE_GETREGS,traced_process,
NULL,&
regs);
ins=ptrace(PTRACE_PEEKTEXT,traced_process,
regs.eip,NULL);
EIP:
%lxInstructionexecuted:
%lx\n"
regs.eip,ins);
ptrace(PTRACE_DETACH,traced_process,
Theaboveprogramsimplyattachestoaprocess,waitsforittostop,examinesitseip(instructionpointer)anddetaches.
Toinjectcodeuseptrace(PTRACE_POKETEXT,..)andptrace(PTRACE_POKEDATA,..)afterthetracedprocesshasstopped.
SettingBreakpoints
Howdodebuggerssetbreakpoints?
Generally,theyreplacetheinstructiontobeexecutedwithatrapinstruction,sothatwhenthetracedprogramstops,thetracingprogram,thedebugger,canexamineit.Itwillreplacetheoriginalinstructiononcethetracingprogramcontinuesthetracedprocess.Here'
sanexample:
constintlong_size=sizeof(long);
voidgetdata(pid_tchild,longaddr,
char*str,intlen)
{char*laddr;
inti,j;
unionu{
longval;
charchars[long_size];
}data;
i=0;
j=len/long_size;
laddr=str;
while(i<
j){
data.val=ptrace(PTRACE_PEEKDATA,child,
addr+i*4,NULL);
memcpy(laddr,data.chars,long_size);
++i;
laddr+=long_size;
j=len%long_size;
if(j!
=0){
memcpy(laddr,data.chars,j);
str[len]='
\0'
;
voidputdata(pid_tchild,longaddr,
memcpy(data.chars,laddr,long_size);
ptrace(PTRACE_POKEDATA,child,
addr+i*4,data.val);
memcpy(data.chars,laddr,j);
structuser_regs_structregs,newregs;
/*int0x80,int3*/
charcode[]={0xcd,0x80,0xcc,0};
charbackup[4];
/*Copyinstructionsintoabackupvariable*/
getdata(traced_process,regs.eip,backup,3);
/*Putthebreakpoint*/
putdata(traced_process,regs.eip,code,3);
/*Lettheprocesscontinueandexecute
theint3instruction*/
ptrace(PTRACE_CONT,traced_process,NULL,NULL);
Theprocessstopped,puttingback"
"
theoriginalinstructions\n"
);
Press<
enter>
tocontinue\n"
getchar();
putdata(traced_process,regs.eip,backup,3);
/*Settingtheeipbacktotheoriginal
instructiontolettheprocesscontinue*/
ptrace(PTRACE_SETREGS,traced_process,
Herewereplacethethreebyteswiththecodeforatrapinstruction,andwhentheprocessstops,wereplacetheoriginalinstructionsandresettheeiptooriginallocation.Figures1-4clarifyhowtheinstructionstreamlookswhenaboveprogramisexecuted.
Figure1.AftertheProcessIsStopped
Figure2.AftertheTrapInstructionBytesAreSet
Figure3.TrapIsHitandControlIsGiventotheTracingProgram
Figure4.AftertheOriginalInstructionsAreReplacedandeipIsResettotheOriginalLocation
Nowthatwehaveaclearideaofhowbreakpointsareset,let'
sinjectsomecodebytesintoarunningprogram.Thesecodebyteswillprint“helloworld”.
Thefollowingprogramisasimple“helloworld”programwithmodificationstofitourneeds.Compilethefollowingprogramwith:
gcc-ohellohello.c
voidmain()
{
__asm__("
jmpforward
backward:
popl%esi#Gettheaddressof
#helloworldstring
movl$4,%eax#Dowritesystemcall
movl$2,%ebx
movl%esi,%ecx
movl$12,%edx
int$0x80
int3#Breakpoint.Herethe
#programwillstopand
#givecontrolbackto
#theparent
forward:
callbackward
.string\"
HelloWorld\\n\"
"
);
Thejumpingbackwardandforwardhereisrequiredtofindtheaddressofthe“helloworld”string.
WecangetthemachinecodefortheaboveassemblyfromGDB.FireupGDBanddisassembletheprogram:
(gdb)disassemblemain
Dumpofassemblercodeforfunctionmain:
0x80483e0<
main>
:
push%ebp
0x80483e1<
main+1>
mov%esp,%ebp
0x80483e3<
main+3>
jmp0x80483fa<
forward>
Endofassemblerdump.
(gdb)disassembleforward
Dumpofassemblercodeforfunctionforward:
0x80483fa<
call0x80483e5<
backward>
0x80483ff<
forward+5>
dec%eax
0x8048400<
forward+6>
gs
0x8048401<
forward+7>
insb(%dx),%es:
(%edi)
0x8048402<
forward+8>
0x8048403<
forward+9>
outsl%ds:
(%esi),(%dx)
0x8048404<
forward+10>
and%dl,0x6f(%edi)
0x8048407<
forward+13>
jb0x8048475
0x8048409<
forward+15>
or%fs:
(%eax),%al
0x804840c<
forward+18>
mov%ebp,%esp
0x804840e<
forward+20>
pop%ebp
0x804840f<
forward+21>
ret
(gdb)disassemblebackward
Dumpofassemblercodeforfunctionbackward:
0x80483e5<
pop%esi
0x80483e6<
backward+1>
mov$0x4,%eax
0x80483eb<
backward+6>
mov$0x2,%ebx
0x80483f0<
backward+11>
mov%esi,%ecx
0x80483f2<
backward+13>
mov$0xc,%edx
0x80483f7<
backward+18>
0x80483f9<
backward+20>
int3
Weneedtotakethemachinecodebytesfrommain+3tobackward+20,whichisatotalof41bytes.ThemachinecodecanbeseenwiththexcommandinGDB:
(gdb)x/40bxmain+3
<
eb155eb804000000
bb0200000089f1ba
backward+14>
0c000000cd80cc
forward+1>
e6ffffff48656c6c
6f20576f726c640a
Nowwehavetheinstructionbytestobeexecuted.Whywait?
Wecaninjectthemusingthesamemethodasinthepreviousexample.Thefollowingisthesourcecode;
onlythemainfunctionisgivenhere:
intlen=41;
charinsertcode[]=
\xeb\x15\x5e\xb8\x04\x00"
\x00\x00\xbb\x02\x00\x00\x00\x89\xf1\xba"
\x0c\x00\x00\x00\xcd\x80\xcc\xe8\xe6\xff"
\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f"
\x72\x6c\x64\x0a\x00"
charbackup[len];
getdata(traced_process,regs.eip,backup,len);
putdata(traced_process,regs.eip,
insertcode,len);
ptrace(PTRACE_CONT,traced_process,
Theprocessstopped,Puttingback"
putdata(traced_process,regs.eip,backup,len);
Lettingitcontinuewith"
originalflow\n"
InjectingtheCodeintoFreeSpace
Inthepreviousexampleweinjectedthecodedirectlyintotheexecutinginstructionstream.However,debuggerscangetconfusedwiththiskindofbehaviour,solet'
sfindthefreespaceintheprocessandinjectthecodethere.Wecanfindfreespacebyexaminingthe/proc/pid/mapsfileofthetr