Which process/thread capabilities sets will be changed during clone(2), unshare(2), and setns(2)? - linux-capabilities

The man page for user_namespaces(7) says:
The child process created by clone(2) with the CLONE_NEWUSER flag starts out with a complete set of capabilities in the new user namespace. Likewise, a process that creates a new user namespace using unshare(2) or joins an existing user namespace using setns(2) gains a full set of capabilities in that namespace.
Unfortunately, the man page does not clarify which capabilities set (or sets) will be affected: one or more of the effective caps set, the permitted caps set, the inheritable caps set, etc. So my question here is: which capabilities sets will be affected by clone(2), unshare(2), and setns(2)?
Note: the example section of user_namespaces(7) seems to indicate that the effective and permitted capabilities set will be fully enabled, while the inherited capabilities are all dropped. However, there is no clear indication that this is fact the implemented behavior. Additionally, there is no indication whether ambient caps are affected or not; and I assume that the bounding caps are unaffected, not least as only cap dropping is possible on bounding caps.

In order to get an idea of what setns(2) and unshare(2) might do to capabilities, I've created the following tiny Python 3 scripts. Make sure to install the package nsenter and unshare (pip3 install nsenter, ...) before any attempt to run them.
setns(2)
# usernscaps.py: dump all capabilities sets of this process
# when entering a specific (grand)child user namespace.
from nsenter import Namespace
import sys
def dumpcaps(s):
print(s)
with open('/proc/self/status', 'r') as st:
for line in st:
if line.startswith('Cap'):
print(line.rstrip())
if len(sys.argv) != 2:
print('usage: usernscaps.py <PID>')
exit(1)
dumpcaps('initial:')
try:
with Namespace('/proc/%d/ns/user' % int(sys.argv[1]), 'user'):
entered = True
dumpcaps('after setns:')
except PermissionError:
# Switching back to our original user namespace isn't allowed, so ignore the exception.
try:
entered
except NameError:
print('no permission to enter user namespace')
As an ordinary unprivileged user, let us create a new user namespace which will be owned by us, and keep it open with a sleeping process (note: we put it to the background):
unshare -U bash -c "readlink /proc/self/ns/user && sleep infinity" &
Next, run the Python script usernscaps.py from above, and tell it to enter our newly created user space using setns(2), then finally dump the capability sets:
python3 usernscaps.py $(lsns -t user | grep "infinity" | awk '{ print $4 }')
This gives, even for our unprivileged user and process, after setns(2):
initial:
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
after setns:
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
This seems to indicate that a setns(2) in fact gives a full set of capabilities not only to the effective caps, but also the permitted caps (which makes sense, as the effective caps must be bounded by the permitted caps at any time). It doesn't seem to top up the inherited caps, though.
clone(2)
Similar to the previous script, but unshare(2)ing this time.
# usernsunsharecaps.py: dump all capabilities sets of this process
# upon unsharing the user namespace.
import unshare
import sys
def dumpcaps(s):
print(s)
with open('/proc/self/status', 'r') as st:
for line in st:
if line.startswith('Cap'):
print(line.rstrip())
dumpcaps('initial:')
unshare.unshare(unshare.CLONE_NEWUSER)
dumpcaps('after unshare:')
Simply run it python3 usernsunsharecaps.py:
initial:
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
after unshare:
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
So, this also gives full permitted and effective capabilities within the new user namespace after unsharing.

Related

Getting import table from DLL

Attaching to DLL as memory dump with WinDbg looks like (for example)
cdb -z %__appdir__%kernel32.dll
It works fine, now I can read NT_IMAGE_HEADER structure
!dh kernel32 -f
For reading export table I use next technique
dd kernel32+262c; * example of an export table RVA;
The is number of exported functions in second column of second row and offset to the start of the export table in first column of third row. Check it
dd kernel32+353c; * example of offset;
...; * take the first address in output;
da kernel32+4ba5
7c804ba5 "ActivateActCtx"
Bingo! Now we can use da again and again to see other exported functions but it's awful way. So it's better to use next trick
? (kernel32+353c); * get hexadecimal address of first exported function;
r? #$t0 = (int *)0x7c80353c; * set the pointer on that address into pseudo-register;
.for (r #$t1 = 0; #$t1 < 3ba; r #$t1 = #$t1 + 1) {da kernel32+(##c++(#$t0[#$t1]));}
What's my problem? At present moment I'm trying to read imported functions but when I type
dps kernel32+1000
where 1000 is RVA to the Import Address Table Directory I've got only part of addresses of names, not names. So, how can I get list of all names of the imported functions? Is there a simplest way or should I write a cycle again? How should be cycle look like?
cdb -z is used for loading dump files
using them for loading binaries have several side effects
and may include not loading pages that belong to import table
import table fill up needs interaction by loader to resolve imported address
when you load a binary as a dumpfile no other modules are loaded along with it
but dump file has information about other dlls needed in the module stream
so when you try to read some data from unloaded memory region
you are presented with ??? (question marks)
actually windbg has three bang commands that you can use for the purpose
they are
!showexports { address / mod }
!showimports { address / mod }
!showresources { address / mod }
the !showimports command also will not work on binary files loaded as dump
(cdb may hang trying to ReadARange and iirc i sent off a mail to windbg team long ago
(during 6.0 or xp era ) but the same hang appears in 17763 windbg which is latest as on the date of post
your efforts to read imports the way you describe will work better if you load an actual dump instead of binary file as dump
to confirm you can use !vadump command and you will see cdb has mapped
pages after the size of import table
C:\>cdb -c "!dh kernel32;q" -z c:\Windows\System32\kernel32.dll | grep -i "Import.*Address"
1000 [ DFC] address [size] of Import Address Table Directory
C:\>cdb -c "dd kernel32+1df0;q" -z c:\Windows\System32\kernel32.dll
Microsoft (R) Windows Debugger Version 10.0.16299.15 X86
Loading Dump File [c:\Windows\System32\kernel32.dll]
0:000> cdb: Reading initial command 'dd kernel32+1df0;q'
77de1df0 ???????? ???????? ???????? 90909090 <<<<<<<<<<<<<
77de1e00 90909090 90909090 90909090 90909090
quit:
C:\>cdb -c "!vadump;q" -z c:\Windows\System32\kernel32.dll
Microsoft (R) Windows Debugger Version 10.0.16299.15 X86
Loading Dump File [c:\Windows\System32\kernel32.dll]
0:000> cdb: Reading initial command '!vadump;q'
BaseAddress: 77de0000
RegionSize: 00001000
BaseAddress: 77de1dfc <<<<<<<<<<<<<<<
RegionSize: 000c4204
BaseAddress: 77ea6000
RegionSize: 00001000
BaseAddress: 77ea7000
RegionSize: 00001000
BaseAddress: 77ea8000
RegionSize: 0000c000
quit:

What is OE+ in Linux?

What is the meaning of (OE+) in the following?
$ sudo cat /proc/modules | grep hello //hello_world is a kernel module created by me.
hello_world 20480 1 - Loading 0xffffffffc0221000 (OE+)
Here is my situation.
I have patched the Linux kernel function load_module(), which is called from finit_module(), the system call used by insmod to insert kernel modules.
The patch looks for a specific module, created by me (called hello_world) being installed, and when it does, it prevents the call to do_init_module(), and returns 0 instead. do_init_call() is responsible for calling a module's init function, and setting the module state to live (MODULE_STATE_LIVE).
When I read /proc/modules, the module state is Loading, which is expected. I do not understand however the meaning of (OE+) at the end of output. This is not displayed against any other module, as is verified by the following command.
$ sudo cat /proc/modules | grep OE
hello_world 20480 1 - Loading 0xffffffffc0221000 (OE+)
I am using Linux kernel v4.7.3.
Update
All this is happening in a Qemu virtual machine. On the host, which is running Linux 4.4.0-36-generic (Ubuntu), I get the following.
$ sudo cat /proc/modules | grep OE
vboxpci 24576 0 - Live 0xffffffffc082a000 (OE)
vboxnetadp 28672 0 - Live 0xffffffffc066e000 (OE)
vboxnetflt 28672 0 - Live 0xffffffffc0635000 (OE)
vboxdrv 454656 3 vboxpci,vboxnetadp,vboxnetflt, Live 0xffffffffc0783000 (OE)
sep4_0 671744 0 - Live 0xffffffffc06de000 (OE)
socperf2_0 36864 1 sep4_0, Live 0xffffffffc0660000 (OE)
pax 16384 0 - Live 0xffffffffc05f9000 (OE)
O means Out-of-tree module has been loaded.
E means Unsigned module has been loaded.
+ means that the module is being loaded.
- means that the module is being unloaded.
The source code for print_modules(), then module_flags(), and then print_tainted() functions may be helpful in figuring out the meaning of these and some other flags. Take a look at the comment just above print_tainted() function. Hope this helps.

Unable to get full user-mode stacktrace while kernel debugging in windbg

I have a virtual Windows 7 x64 machine on a Windows 10 host, and I kernel debug it with windbg 10.0.10586.567. I'm running my own application on it, which I have full source and private symbols for. Whenever I break in and ask for stack traces of the app's threads, the backtrace always stops when one of my application's binaries are "hit."
So for instance, if I break in, switch to the process, and request a stacktrace with !thread [thread address] 1f, I get something like this (note the "early" zero return address at the last line):
fffff880`0534e870 fffff800`026d6992 nt!KiSwapContext+0x7a
fffff880`0534e9b0 fffff800`026d81a2 nt!KiCommitThreadWait+0x1d2
fffff880`0534ea40 fffff800`029c7a2e nt!KeDelayExecutionThread+0x186
fffff880`0534eab0 fffff800`026d08d3 nt!NtDelayExecution+0x59
fffff880`0534eae0 00000000`76e7165a nt!KiSystemServiceCopyEnd+0x13 (TrapFrame # fffff880`0534eae0)
00000000`00276708 000007fe`fcf91203 ntdll!NtDelayExecution+0xa
00000000`00276710 00000001`410e7dd9 KERNELBASE!SleepEx+0xab
00000000`002767b0 00000000`00000000 MyApp!MainMessageLoop+0x4b1 [d:\whatever\path\myapplication.cpp # 3024]
This looks very similar to when you you are missing a binary while debugging a user-mode dump (lack of unwind data) of an x64 process, except in that case the stack trace usually does not stop "this sudden", rather it goes astray at that point, and shows bogus values.
Some extra info/things I tried:
I have the correct symbol paths set up (both the Microsoft symbol server, and a local folder on the host with matching PDBs, even though the latter is not needed for just the stack trace)
I have a binary path set up (.exepath) containing matching binaries on the host (I've made absolutely sure of this; copied the binaries directly from the guest to the host machine)
If I put a breakpoint in one of the app's exported DLL functions, then when the debugger breaks in, I get a one-liner stack trace like this: 0000000000274b40 0000000000000000 MyAppDLL!SomeExportedFunction+0x32 [d:\whatever\path\myapplicationDLL.cpp # 232]
I've tried virtually every combination of commands to get a stacktrace (.process /i, .process /r /p, !process -1 7, .reloads, .reload /users, .reload /f MyApp.exe, !thread [address] 1f, etc.) with no success
Tried with an older version of windbg (6.11.0001.404) as well, same result
Also tried on Windows 8.1 as a guest with the very same binaries, same result
!sym noisy output (irrelevant lines omitted):
0: kd>.process /i [address]
0: kd>g
0: kd>.reload /user
0: kd> !process -1 2
0: kd> !thread [address] 1f
[...]
DBGHELP: d:\symbolcache\MyApp.pdb\76931C5A6C284779AD2F916CA324617E1\MyApp.pdb already cached
DBGHELP: MyApp - private symbols & lines
[...]
lmvm MyApp output:
[...]
Loaded symbol image file: MyApp.exe
Image path: C:\MyApp\MyApp.exe
[...]
Any ideas?
I accidentally stumbled into a linker switch that solves this problem: /DEBUGTYPE with the PDATA argument. If you link your binaries with this switch, unwind information will be copied into your PDBs.
I recompiled/relinked the application in question with /DEBUGTYPE:CV,PDATA (/DEBUGTYPE:CV is the default if /DEBUG is specified, see the documentation), now everything works like a charm, I always get full call stacks.
One strange aspect of this: windbg happily uses unwind data found in the PDBs, but ignores the very same data in the mapped binaries (both on the host machine).
This is not a perfect solution to the problem (or any solution at all, one might say), but I'm providing this provisional answer with a workaround.
You should be able to get the information you want, albeit not so well-formatted using something like dps #rsp L10.
In x86-64 you don't have a parallel of the x86 ebp-chain, but the return addresses are still on the stack. Those will give you the functions in the stack, and the values between them will be the arguments passed to the functions (and saved registers on the stack, etc.). A random example from Google (as I'm not on my Windows machine right now):
0:017> dps #rsp
00000000`1bb0fbb8 00000000`00000020
00000000`1bb0fbc0 00000000`00000000
00000000`1bb0fbc8 00000000`008bc6c6 Dolphin!ReadDataFromFifoOnCPU+0xb6 [d:\sources\comex\source\core\videocommon\fifo.cpp # 245]
00000000`1bb0fbd0 00000000`1ba0ffeb
00000000`1bb0fbd8 00000000`00000020
00000000`1bb0fbe0 00000000`00000020
00000000`1bb0fbe8 00000000`00000800
00000000`1bb0fbf0 00000000`1ba0ffeb
00000000`1bb0fbf8 00000000`008c2ff5 Dolphin!InterpretDisplayListPreprocess+0x45 [d:\sources\comex\source\core\videocommon\opcodedecoding.cpp # 87]
00000000`1bb0fc00 00000000`00000000
00000000`1bb0fc08 00000000`008bc041 Dolphin!RunGpu+0x81 [d:\sources\comex\source\core\videocommon\fifo.cpp # 389]
00000000`1bb0fc10 00000000`8064cbc0
00000000`1bb0fc18 00000000`1bb0fcc0
00000000`1bb0fc20 00000000`00000000
00000000`1bb0fc28 00000000`008c2dda Dolphin!OpcodeDecoder_Preprocess+0x14a [d:\sources\comex\source\core\videocommon\opcodedecoding.cpp # 326]
00000000`1bb0fc30 00000000`8064cbe0
Given that you have symbols, the return addresses are easily distinguishable.
The unwind data is lazy loaded for user mode modules, so it's not going to be mapped unless someone needs it. Unfortunately the kernel debugger doesn't force the information to be present for user images, so sometimes you get this behavior. You can see if the data is mapped or not by dumping the PE header (!dh) and checking the state of the Exception Directory (!pte imagename+offset).
Given that you own the app, try forcing the information to be resident by doing a stack walk NOP somewhere in your app:
PVOID stack[2];
(VOID)CaptureStackBackTrace(0, 2, (PVOID*)&stack, NULL);
That doesn't guarantee the entire directory will be present, but usually good enough.

How to break on the entry point of a program when debug in kernel mode with windbg?

I want to debug a program in kernel mode, and I want to break on the entry point of the program like ollydbg. But I can't break it with bp because the program is not start and the symbol can't be loaded. I have found some way to do it but I think it's not so good.
1.Break on the CreateProcess function in kernel. But I don't know which function exactly should I break and I think there is a long way between CreateProcess and the entry point of the program.
2.Change the entry point of the program with cc. But it needs other tools and I should change the code where the byte changed back. I think it is annoying.
3.With the help of ollydbg. Debugging the program with ollydbg in a virtual machine which is debugged with windbg. I don't think that it is a good idea.
4.Use sxe ld. It can be found on Listing 3.29 in <<Advanced Windows Debugging>>. I have tried it but I found that it only works on the first time. And I don't know what exactly should I do after the break.
5.Break on the entry function with bu. But I don't know what exactly I should do either. For example, how to load the symbol?
6.Use .create. I don't know whether it is properly or not to do what I said.
I think that it is a common use to break on the entry point of a program when debug in kernel mode with windbg , and I think that there must be a good way to do that with the powerful windbg. What's the best way to do it?
By the way, I want to debug a program in kernel mode because I want to get the token vaule of the program. I found that the windbg can identify the token with !token in user mode, but I don't know how to get the value of token in user mode. It seems that I can only get the value of token in the kernel mode, right or wrong?
you can run any exe in the target via ntsd -d to debug it from the kernel mode debugger running in the host
assuming you are running a virtual machine mytarget inside myhost
install windbg in myhost
set symbol path for myhost viz srv*x:\xxxx*http:\xxxxxxxxxxxx
create a kernel connection in the host (choose the best shown below is a serial connnection)
X:\xxxx\windbg.exe -k com:pipe,port=\\.\pipe\debugPipe,resets=0,reconnect
install windbg in mytarget
open a shared folder z:\ pointing to the symbolcache folder in myhost
set symbolpath in mytarget pointing to the shared folder
run ntsd -d calc.exe
kd will break on $exentry of calc.exe with Input Prompt
as long as Input prompt is shown you are using kd like a native usermode debugger
so if you set a bp calc!Winmain and issue g kd will break on calc.exe winmain
to get to kd session use .breakin
messy stuff but will work well once you get accustomed (ie memorizing the docs)
a sample run
kd> g <-------------- kd session running in myhost
CommandLine: calc.exe
Symbol search path is: srv*z:\
*http://msdl.microsoft.com/download/symbols
ntdll!DbgBreakPoint:
7c90120e cc int 3
.sympath
NOTE: The symbol path for this ntsd is relative to where
ntsd.exe is running, not where kd.exe is running.
Symbol search path is: srv*z:\
*http://msdl.microsoft.com/download/symbols
Expanded Symbol search path is: srv*z:\
*http://msdl.microsoft.com/download/symbols
.reload /f calc.exe
lm m calc
start end module name
01000000 0101f000 calc (pdb symbols) z:\calc.pdb\3B7D84101\calc.pdb
0:000> version <--------------------usermode session in kd via ntsd -d
version
Windows XP Version 2600 (Service Pack 3) UP Free x86 compatible
Live user mode: <Local>
command line: 'ntsd -d calc.exe' Debugger Process 0x3F8
? $exentry;? calc!WinmainCrtstartup
Evaluate expression: 16852085 = 01012475
Evaluate expression: 16852085 = 01012475
as to your original request i am not sure what token you are interested to find
if getting the EPROCESS->Token of your exe is the only requirement you dont have to run any kd session
you can get the token of all running process in myhost with a local kernel debugging session (either using kd -kl or by using livekd from sysinternals)
here is a simple script which fetches the sid of all running process employing the above technique
:\>cat sid.txt
!for_each_process "r $t0 =(##c++(((nt!_eprocess *) ##Process )->Token.Object)) &
##(~7); r $t1 = ##c++(((nt!_token *) #$t0 )->UserAndGroups->Sid);!sid #$t1 1; ?
? (char *)((nt!_eprocess *) ##Process )->ImageFileName "
:\>kd -kl -c "$$>a< sid.txt;q"
result
WARNING: Local kernel debugging requires booting with kernel
debugging support (/debug or bcdedit -debug on) to work optimally.
lkd> kd: Reading initial command '$$>a< sid.txt;q'
SID is: S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)
char * 0x8ac729a4
"System"
SID is: S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)
char * 0x8a35729c
"smss.exe"
SID is: S-1-5-20 (Well Known Group: NT AUTHORITY\NETWORK SERVICE)
char * 0x8a3619ac
"svchost.exe"
SID is: S-1-5-19 (Well Known Group: NT AUTHORITY\LOCAL SERVICE)
char * 0x8a36ef14
"svchost.exe"
SID is: S-1-5-21-602162358-1801674531-1417001333-1003 (User: XXXXXX\Admin)
char * 0x8a261b64
"explorer.exe"
Use the method described in the Windbg help file for debugging WinLogon. Substitute your user mode app for WinLogon:
Windbg | Help | Contents | Windows Debugging | Debugging Techniques | Specialized Debugging Techniques | Debugging WinLogon
IFEO will start your user mode app and attach ntsd.exe. From ntsd.exe, you can set a break point on image entry with bu $exentry then g to continue.
At any point that ntsd.exe is broken into your user mode process, you can issue .breakin command to switch to kernel mode debugging.

How to view the GDTR's value?

In the book "Rootkit Arsenal" page 84 (Chapter 3) mentions:
..., we can view the contents of the
target machine's descriptor registers
using the command with the 0x100 mask:
kd> rM 0x100
and a paragraph below:
Note that the same task can be
accomplished by specifying the GDTR
components explicitly: kd> r gdtr ....
I run Windbg on my Win XP (inside VMWare) and choose the Kernel Debug -> Local.
My problem is in case of first command, windbg errors with:
lkd> rM 0x100
^ Operation not supported in current debug session 'rM 0x100'
and in the second command:
lkd> r gdtr
^ Bad register error in 'r gdtr'
Can anyone guide me ?
Right, you can't look at registers in a local kernel debug session. LiveKD works and you can also get the address indirectly through the PCR (!pcr).
-scott
I think I've found the solution:
Use two computers for kernel debugging instead of Local Kernel Debug.
(I used VMWare and am debugging through the COM port/named pipe)
I am thinking why this facility/feature (Local Kernel Debugging) is there if it's not complete ?

Resources