Информация об изменениях

Сообщение Re[4]: Linux: царь^w root ненастоящий! от 07.09.2016 19:31

Изменено 16.09.2016 22:25 IID

Здравствуйте, andrey.desman, Вы писали:


AD>Ты из adb запускаешь? Я посмотрел код adb демона — он дропает cap_setuid/cap_setgid из своего bounding set. Получить их обратно уже невозможно, даже если запускать setuid бинарь.


Патч ADB демона, изменяющий всего 2 байта и отучающий его от такого поведения (чтобы не менять system-wide props, как это штатным образом положено).


import sys
import os

syscall_prctl   = "\xAC\x70\xA0\xE3\x00\x00\x00\xEF" # mov r7, #172; svc 0
syscall_replace = "\xAC\x70\xA0\xE3\x00\x00\xE0\xE3" # mov r7, #172; mov r0, -1

def patch_adbd(adbd_path):
    print("Patching adbd daemon file: \"%s\"" % adbd_path)
    data = open(adbd_path, "rb").read()
    offset = data.find(syscall_prctl)
    if offset < 0:
        print("ERROR: \"syscall prctl\" not found!")
        return

    if data.find(syscall_prctl, offset+1) >= 0:
        print("ERROR: too many \"syscall prctl\" found!")
        return

    new_content = data[:offset] + syscall_replace + data[offset+len(syscall_replace):]
    open(adbd_path + ".patched", "wb").write(new_content)


if len(sys.argv) <= 1:
    print("Usage: %s path_to_adbd" % os.path.basename(sys.argv[0]))
else:
    patch_adbd(sys.argv[1])
Re[4]: Linux: царь^w root ненастоящий!
Здравствуйте, andrey.desman, Вы писали:


AD>Ты из adb запускаешь? Я посмотрел код adb демона — он дропает cap_setuid/cap_setgid из своего bounding set. Получить их обратно уже невозможно, даже если запускать setuid бинарь.


Патч ADB демона, изменяющий всего 2 байта и отучающий его от такого поведения (чтобы не менять system-wide props, как это штатным образом положено).

UPD: для JellyBean и ниже нужен свой патч.


import sys
import os

syscall_prctl   = "\xAC\x70\xA0\xE3\x00\x00\x00\xEF" # mov r7, #172; svc 0
syscall_capset  = "\xB9\x70\xA0\xE3\x00\x00\x00\xEF" # mov r7, #185; svc 0
mov_r0_munus1   = "\x00\x00\xE0\xE3" # mov r0, -1
mov_r0_zero     = "\x00\x00\xA0\xE3" # mov r0, 0

def patch_adbd(ver, adbd_path):
    if "kk" == ver:
        pattern = syscall_prctl
        replacement = pattern[0:4] + mov_r0_munus1  # mov r7, #172; mov r0, -1

    elif "jb" == ver:
        pattern = syscall_capset
        replacement = pattern[0:4] + mov_r0_zero    # mov r7, #185; mov r0, 0
    else:
        print("Wrong OS version: %s\n", ver)
        return

    print("Patching adbd daemon file: \"%s\"" % adbd_path)
    data = open(adbd_path, "rb").read()
    offset = data.find(pattern)
    if offset < 0:
        print("ERROR: pattern not found!")
        return

    if data.find(pattern, offset+1) >= 0:
        print("ERROR: too many patterns found!")
        return

    new_content = data[:offset] + replacement + data[offset+len(replacement):]
    open(adbd_path + ".patched", "wb").write(new_content)
    print("OK!\n")


if len(sys.argv) <= 2:
    print("Usage: %s kk|jb path_to_adbd\n  kk - for adbd >= KitKat\n  jb - for adbd <= JellyBean\n" % os.path.basename(sys.argv[0]))
else:
    patch_adbd(sys.argv[1], sys.argv[2])