Bypass ptrace anti-debugging trick - debugging

I'm having some trouble bypassing calls to ptrace when debugging a 32-bit Linux executable.
I have this binary: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.26, BuildID[sha1]=b1579d4c55e90110491da76331c9a158b77a5729, stripped
and i have been trying to debug it. So due to it is a stripped binary i located the entry point using gdb.
gef➤ info file
Entry point: 0x804849c
.
.
.
other stuff
Once I got to the entry point, I printed out the next instructions:
gef➤ x/15i 0x804849c
0x804849c: xor ebp,ebp
0x804849e: pop esi
0x804849f: mov ecx,esp
0x80484a1: and esp,0xfffffff0
0x80484a4: push eax
0x80484a5: push esp
0x80484a6: push edx
0x80484a7: push 0x8048580
0x80484ac: push 0x8048590
0x80484b1: push ecx
0x80484b2: push esi
0x80484b3: push 0x8048480
0x80484b8: call 0x8048350 <__libc_start_main#plt>
0x80484bd: hlt
0x80484be: nop
I know 0x8048480 is the address of the main function. Now i placed a breakpoint at main (0x8048480) and then ran the program but i can't step into the breakpoint and the program exit with code 01. Therefore i decided to run strace ./binary command and ptrace calls inhibit me from debugging any further:
ptrace(PTRACE_TRACEME) = -1 EPERM (Operation not permitted)
To bypass this, i tried to use the LD_PRELOAD environment variable.
Hence i created a simple .c file:
long ptrace(int request, int pid, void *addr, void *data) {
return 0;
}
And compiled it as a shared library with the following command:
gcc -fPIC -shared -m32 ptrace.c -o ptrace.so
Here the output of the command file ptrace.so
ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=a9de523da44299f76ad94373a07c9c5f6f3c76db, not stripped
Next I set the environment variable LD_PRELOAD in the shell using export LD_PRELOAD=./ptrace.so command first, and then within gdb set environment LD_PRELOAD=./ptrace.so
but this is the output:
ERROR: ld.so: object './ptrace.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
How can i bypass the ptrace call??
Thank you.

To bypass this, i tried to use the LD_PRELOAD environment variable.
If the application is employing anti-debugging tricks, it is exceedingly likely that it executes ptrace system call directly, rather than via libc wrapper. LD_PRELOAD will not work in that case.
This command:
gcc -shared ptrace.c -o ptrace.so
builds a 64-bit binary on a 64-bit system. You want:
gcc -fPIC -shared -m32 ptrace.c -o ptrace.so

Related

are there debugging options for ld

I have written an assembly program that, for testing purposes, just exits. The code is as follows:
section .text
_global start
_start:
mov eax, 1
mov ebx, 0
int 0x80
The program is obviously in 32-bit; however, I am using 1 64-bit processor and operating system, so I compiled it (using nasm) and linked it as follows:
nasm -f elf exit.asm
ld -m elf_i386 -s -o exit exit.o
debugging the program with gdb, I can't list the code since there are no debugging symbols.
(gdb) list
No symbol table is loaded. Use the "file" command.
In using gcc, you can use the options -ggdb to load the symbols while compiling a c file. but since I don't how to use gcc to compile 32-bit assembly for 64-bit machines (I have searched this but can't find a solution,) I am forced to use ld. can I load the debugging symbols using ld? sorry for the long question and the excess information. Thanks in advance.
Debugging information is generated by nasm when you pass -g. Additionally, you also need to specify what type of debugging information you want (typically dwarf), which is done with the -F switch. So to assemble your file, write
nasm -f elf -F dwarf -g file.asm
then link without -s to preserve the symbol table and debugging information:
ld -m elf_i386 -o file file.o
The -s switch tells ld to "strip" the debugging info. Lose that!

Windows x86 assembly entry point is wrong

I wrote a test program for learning purposes in x86 assembly using NASM as assembler and MinGW32 (ld) as linkerW.
I am working on Windows 10.
section .text
global my_start
my_start:
nop
nop
nop
nop
jmp my_start
I am using the following command for assembling:
nasm -f win32 -l main.lst main.asm
And the following command for linking:
ld -nostdlib -nostartfiles -s -o main.exe -e my_start main.obj
Now if I run the program I get an sgmentation fault error.
To find out why I used GDB for debugging and found out that windows is executing my executable at file begin where the DOS Header is laying.
So windows is trying to execute the magic number "MZ" (4d 5a) and following bytes as assembler instructions.
So, now I am very confused why this happens because I specified an entry point (-e my_start) followed by valid x86 assembler instructions.
Why exactly my executable start's execute at DOS header and not at my specified entry point in my code segment?
How I can fix this?
EDIT:
I tried now GoLink and using this linker everything is working fine:
GoLink.exe main.obj /entry my_start
I also compared the entry point of the optional header and both are equal.
But comparing both files a lot of things are different so I cannot tell what exactly is wrong so I will stick with GoLink for a while and maybe come back to this problem if I have a bit more experience.

How to link 32-bit Nasm assembly object code on a 64-bit windows computer

I found the following code from http://www.dreamincode.net/forums/topic/328714-my-program-keeps-crashing/.
global start
;~ msvcrt.dll
extern _printf
%define printf _printf
;~ kernel32.dll
extern ExitProcess, GetCommandLineW, LocalFree
%define GetCommandLine GetCommandLineW
;~ shell32.dll
extern CommandLineToArgvW
%define CommandLineToArgv CommandLineToArgvW
SECTION .data
message db 'Hello, World', 13, 10, 0
fmtstr db "%s", 0
fmtstrCL db "Arg","%d", " = ", "%S", 13, 10, 0
section .bss
pNumArgs resd 1
section .text
start:
call GetCommandLine
push pNumArgs
push eax
call CommandLineToArgv
mov esi, eax
mov ebx, [pNumArgs]
DisplayArgs:
dec ebx
push dword[esi + 4 * ebx]
inc ebx
push ebx
push fmtstrCL
call printf
add esp, 4 * 3
dec ebx
jnz DisplayArgs
push esi
call LocalFree
push message ; Push address of "Hello, world!" onto the stack
push fmtstr ; push address of formatter onto the stack
call printf ; Print the message
add esp, 4 * 2 ; adjust stack pointer
push 0
call ExitProcess
My goal is to learn assembly language by reading other people's code and eventually write my own. I cannot figure out how to link 32-bit assembly programs on my 64-bit windows computer.
To assemble the program I use the command:
nasm -f win32 hello32.asm -o hello32.o
To link the object file I use:
gcc hello32.o -o hello32.exe
After I issue the link command I get the following error:
C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: i386 arc
hitecture of input file `hello32.o' is incompatible with i386:x86-64 output
hello32.o:hello32.asm:(.text+0x24): undefined reference to `_printf'
hello32.o:hello32.asm:(.text+0x3f): undefined reference to `_printf'
C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw3
2.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined refere
nce to `WinMain'
collect2.exe: error: ld returned 1 exit status
I am using 64-bit mingw binaries that are supposed to be compatible with making 32-bit programs. I have tried switching to 32-bit mingw binaries and I get a massive amount of undefined reference errors. I can link simple skeleton files without any problems using the above commands. I have no idea what I am doing wrong and I would appreciate any guidance someone could give me.
i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output
NASM has created a 32 bit object file, but you are trying to link a 64 bit executable. You could try to use the -m32 switch to create a 32 bit executable, but you already found out that this causes another bunch of errors. I do not have a solution for that either.
To link your executable, use a 32 bit MingW environment. I tried MinGW4.6.2 32 bit which worked well.
Alternatively, you can use the linker (link.exe) from a Microsoft Visual Studio installation.
https://github.com/afester/CodeSamples/tree/master/Asm/nasm_win32 shows a hello world example together with a Makefile which uses the Visual Studio linker. Alternatively, using gcc helloworld.obj -o hello32.exe from a MingW32 installation works also.
Two issues:
You're using the option -f win32 but asking for the object file in *.o extension. The two formats, .o and .obj are not compatible. But of course, you're free to specify your own extension, and so nasm will obediently assemble your code into a file with i386 arc format .o file.
Next, you're asking gcc to build that hello32.exe, using the file hello32.o. Effectively, you gave gcc an arc format .o file, and asked to build a 64-bit PE format executable out of it. And then (naturally) gcc complains:
i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output
which is correct.
Two ways you can fix this:
Assemble with: nasm -fwin32 hello32.asm and then, link with gcc -m32 hello32.obj -o hello32.exe
Assemble with: nasm -fobj hello32.asm and then link with alink -subsys console -oPE hello32.o. You can get alink from here.
Let me know which worked for you.
P.S. I have outlined the problems I have faced myself in this blog, hope that helps.

NASM debug symbols for Windows?

I am trying to learn x86 assembly on Windows. I can assemble and link a program successfully using:
nasm -f win32 -g sandbox.asm -l sandbox.lst
ld -mi386pe -o sandbox.exe sandbox.obj
But when I try running my program with gdb, it says that it can't find the debug symbols. Nasm says that only the "null" debug symbol format is available for win32. Does this mean that it can't generate debug symbols for windows? If so, then how can I debug my program on windows?
Here is the example program that I am using:
section .data
section .bss
section .text
global start
start:
mov ebp, esp
mov eax, 0
ret
You must specify the debugging format to include in your binary (sometimes there is not one by default)
try -gcv8 instead of -g

Details on gdb memory access complaint

I have an object file compiled using as (from assembler code).
If I link it using ld, when I try to stepi (or nexti) gdb complains about memory access at address 0x0. If I link it using gcc, all is fine.
I am guessing the problem is caused by ld, which produces fewer sections when compared to the linking result of gcc.
Is there a way to configure gdb to be more verbose so I can maybe figure out what's wrong with the executable?
(gdb) b main
Breakpoint 1 at 0x100000f8e
(gdb) r
Breakpoint 1, 0x0000000100000f8e in main ()
(gdb) x/10i $pc
0x100000f8e <main>: fbld 0x6c(%rip) # 0x100001000 <data1>
0x100000f94 <main+6>: fimul 0x7a(%rip) # 0x100001014 <data2>
0x100000f9a <main+12>: fbstp 0x60(%rip) # 0x100001000 <data1>
0x100000fa0 <main+18>: mov0x0 $0x2000001,%rax
0x100000fa7 <main+25>: mov $,%rdi
0x100000fae <main+32>: syscall
(gdb) si
Cannot access memory at address 0x0
0x0000000100000f94 in main ()
PS: The executable itself runs as expected in both versions.
Later edit: commands i've used to compile:
as -arch x86_64 src.s -o src.o
ld -e _main -arch x86_64 src.o -o src
gcc -o src src.o
gdb has a "show debug" command, giving various internal debug settings. E.g. "set debug target 1" will turn on tracing for gdb's interaction with the target process. You might want to experiment with every flag they have (there aren't that many).
GCC doesn't actually do the linking, it just calls ld on your behalf. The options it's providing must be different from the ones you are using.
Per this thread:
How to get GCC linker command?
You should be able to see the ld invocation's command line by running gcc -v.
That should tell you how to modify your ld command line so things work for you.

Resources