public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int menu = 0;
String find = null; // switch문 내에서 문자열을 받을때 사용하는 변수
Proc p = new Proc(); // 함수 호출 용도로 생성
while(true)
{
System.out.println("=====프로세스 관리=====");
System.out.println("1. 프로세스 목록");
System.out.println("2. 프로세스 이름 검색");
System.out.println("3. 프로세스 ID 검색");
System.out.println("4. 프로세스 이름으로 종료");
System.out.println("5. 프로세스 ID로 종료");
System.out.print("번호 입력: ");
menu = input.nextInt(); // menu변수에 숫자를 입력
input.nextLine(); // 개행이 남아있기 때문에 비워주기 위한 용도
switch (menu) { // menu변수를 통해 해당하는 맞는 함수를 호출
case 1:
System.out.println("프로세스 목록");
p.list_all(); // 프로세스 리스트 조회용 함수
break;
case 2:
System.out.print("프로세스 이름 입력 : ");
find = input.nextLine();
p.img_find(find); // 프로세스 이름으로 조회하는 함수
break;
case 3:
System.out.print("프로세스 ID 입력 : ");
find = input.nextLine();
p.pid_find(find); // 프로세스 ID로 조회하는 함수
break;
case 4:
System.out.print("프로세스 이름 입력 : ");
find = input.nextLine();
p.img_kill(find); // 프로세스 이름을 통해 종료하는 함수
break;
case 5:
System.out.print("프로세스 ID 입력 : ");
find = input.nextLine();
p.pid_kill(find); // 프로세스 ID를 통해 종료하는 함수
break;
default:
break;
}
}
}
Proc 함수 코드
public class Proc {
// 프로세스 리스트 조회 함수
public void list_all() {
ArrayList<String> list = new ArrayList<String>();
// Arraylist에 조회하는 명령어를 옵션별로 잘라서 넣어준다
list.add("TASKLIST");
list.add("/SVC");
list.add("/FO");
list.add("CSV");
String data = null; // 명령어를 통해 나온 내용을 저장하는 변수
// 예외처리
try {
// Process객체를 생성
// 외부 프로그램을 실행시키는 ProcessBuilder에 list를 넣고 실행
Process ps = new ProcessBuilder(list).start();
// ps의 결과 값을 byte로 받아서 문자로 처리하게 해준다
InputStreamReader in = new InputStreamReader(ps.getInputStream());
BufferedReader br = new BufferedReader(in);
// cmd 창에서 조회를 했을 때 나오는 첫 번째 쓸모 없는 라인을 가져온다
data = br.readLine();
// 반복문을 통해 프로세스 리스트를 다 가져온다
while (true) {
// 한번 더 읽어들여 처음 읽은걸 버린다
data = br.readLine();
// data에 내용이 없을 경우 반복문을 빠져나간다
if (data == null) {
break;
}
// \로 작성된 것을 공백으로 변환한다
data = data.replaceAll("\"", "");
// data 변수에 담긴 값에서 ','을 기준으로 잘라 0번지와 1번지를 가져오고 출력
System.out.printf("%s\t%s\n", data.split(",")[0], data.split(",")[1]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 프로세스 이름으로 조회하는 함수
public void img_find(String dst) {
ArrayList<String> list = new ArrayList<String>();
// Arraylist에 조회하는 명령어를 옵션별로 잘라서 넣어준다
list.add("TASKLIST");
list.add("/SVC");
list.add("/FO");
list.add("CSV");
String data = null; // 명령어를 통해 나온 내용을 저장하는 변수
String src = null; // 프로세스 이름을 담을 변수
// 예외처리
try {
// Process객체를 생성
// 외부 프로그램을 실행시키는 ProcessBuilder에 list를 넣고 실행
Process ps = new ProcessBuilder(list).start();
// ps의 결과 값을 byte로 받아서 문자로 처리하게 해준다
InputStreamReader in = new InputStreamReader(ps.getInputStream());
BufferedReader br = new BufferedReader(in);
// cmd 창에서 조회를 했을 때 나오는 첫 번째 쓸모 없는 라인을 가져온다
data = br.readLine();
// 반복문을 통해 프로세스 리스트를 다 가져온다
while (true) {
// 한번 더 읽어들여 처음 읽은걸 버린다
data = br.readLine();
// data에 내용이 없을 경우 반복문을 빠져나간다
if (data == null) {
break;
}
// \로 작성된 것을 공백으로 변환한다
data = data.replaceAll("\"", "");
// data 변수에 담긴 값에서 ','을 기준으로 잘라 0번지를 가져옴
src = data.split(",")[0];
// src값과 dst값이 같은지 비교한다
if(src.equals(dst))
{
// data 변수에 담긴 값에서 ','을 기준으로 잘라 0번지와 1번지를 가져오고 출력
System.out.printf("%s\t%s\n", data.split(",")[0], data.split(",")[1]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 프로세스 ID로 조회하는 함수
public void pid_find(String dst) {
ArrayList<String> list = new ArrayList<String>();
// Arraylist에 조회하는 명령어를 옵션별로 잘라서 넣어준다
list.add("TASKLIST");
list.add("/SVC");
list.add("/FO");
list.add("CSV");
String data = null; // 명령어를 통해 나온 내용을 저장하는 변수
String src = null; // 프로세스 이름을 담을 변수
// 예외처리
try {
// Process객체를 생성
// 외부 프로그램을 실행시키는 ProcessBuilder에 list를 넣고 실행
Process ps = new ProcessBuilder(list).start();
// ps의 결과 값을 byte로 받아서 문자로 처리하게 해준다
InputStreamReader in = new InputStreamReader(ps.getInputStream());
BufferedReader br = new BufferedReader(in);
// cmd 창에서 조회를 했을 때 나오는 첫 번째 쓸모 없는 라인을 가져온다
data = br.readLine();
// 반복문을 통해 프로세스 리스트를 다 가져온다
while (true) {
// 한번 더 읽어들여 처음 읽은걸 버린다
data = br.readLine();
// data에 내용이 없을 경우 반복문을 빠져나간다
if (data == null) {
break;
}
// \로 작성된 것을 공백으로 변환한다
data = data.replaceAll("\"", "");
// data 변수에 담긴 값에서 ','을 기준으로 잘라 1번지를 가져옴
src = data.split(",")[1];
// src값과 dst값이 같은지 비교한다
if(src.equals(dst))
{
// data 변수에 담긴 값에서 ','을 기준으로 잘라 0번지와 1번지를 가져오고 출력
System.out.printf("%s\t%s\n", data.split(",")[0], data.split(",")[1]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 프로세스 이름을 통해 종료하는 함수
public void img_kill(String find) {
ArrayList<String> list = new ArrayList<String>();
// Arraylist에 프로세스 종료 명령어를 옵션별로 잘라서 넣어준다
list.add("TASKKILL");
list.add("/F");
list.add("/IM");
list.add(find);
// 명령어를 통해 나온 내용을 저장하는 변수
String data = null;
//예외처리
try {
// Process객체를 생성
// 외부 프로그램을 실행시키는 ProcessBuilder에 list를 넣고 실행
Process ps = new ProcessBuilder(list).start();
// ps의 결과 값을 byte로 받아서 문자로 처리하게 해준다
InputStreamReader in = new InputStreamReader(ps.getInputStream());
BufferedReader br = new BufferedReader(in);
// cmd 창에서 프로세스를 종료 했을 때 나오는 첫 번째 쓸모 없는 라인을 가져온다
data = br.readLine();
// data에 내용이 없으면 반복문에 들어가지 않는다
// 프로세스 종료가 성공적으로 되었으면 종료시 나오는 메시지를
// 반복문을 통해 전부 출력한다
while (data != null) {
System.out.println(data);
data = br.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 프로세스 ID를 통해 종료하는 함수
public void pid_kill(String find) {
ArrayList<String> list = new ArrayList<String>();
// Arraylist에 프로세스 종료 명령어를 옵션별로 잘라서 넣어준다
list.add("TASKKILL");
list.add("/F");
list.add("/PID");
list.add(find);
// 명령어를 통해 나온 내용을 저장하는 변수
String data = null;
// 예외처리
try {
// Process객체를 생성
// 외부 프로그램을 실행시키는 ProcessBuilder에 list를 넣고 실행
Process ps = new ProcessBuilder(list).start();
// ps의 결과 값을 byte로 받아서 문자로 처리하게 해준다
InputStreamReader in = new InputStreamReader(ps.getInputStream());
BufferedReader br = new BufferedReader(in);
// cmd 창에서 프로세스를 종료 했을 때 나오는 첫 번째 쓸모 없는 라인을 가져온다
data = br.readLine();
// data에 내용이 없으면 반복문에 들어가지 않는다
// 프로세스 종료가 성공적으로 되었으면 종료시 나오는 메시지를
// 반복문을 통해 전부 출력한다
while (data != null) {
System.out.println(data);
data = br.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 컴퓨터의 기억 장소에서 그 일부분이 프로그램들에 할당되었다가 회수되는 작용이 되풀이 되는 영역이다 - 보통 포인터를 통해 동적으로 할당 받고 돌려준다 - 프로그램 실행시 크기가 결정된다 - 낮은 주소에서 높은 주소로 할당된다 - 리스트, 트리, 그래프 등의 동적인 자료구조에 꼭 필요하다
Heap Buffer Overflow란 : heap 데이터 영역에서 일어나는 buffer overflow를 heap overflow라 부르며 stack에서와 같이 RET 변조는 불가하고 동적 메모리 할당 연결을 덮어씀으로써 프로그램 함수 포인터를 조작한다
Heap Buffer Overflow 순서
1. root 계정에서 취약한 함수를 사용한 파일 작성
2. 일반 계정에서 변수 사이의 거리를 확인
3. 공격 코드 작성
1. root 계정에서 취약한 함수를 사용한 파일 작성
- root 계정에서 취약한 함수가 사용되어진 파일을 작성해준다 /tmp/heap.c
- 컴파일을 해준 후 setuid 비트를 걸어준다
2. 일반 계정에서 변수 사이의 거리를 확인
- root가 만들어 놓은 취약한 프로그램을 같은 글자수로 복사
- gdb를 통해 복사한 파일을 열어주고 intel문법으로 변환 시켜준다
- 첫 번째 변수의 주소는 ebp-4에 닮기고 두 번째 변수의 주소는 ebp-8에 닮기는걸 확인할 수 있다
- ebp-4와 ebp-8의 주소 값을 구하고 큰 수에서 작은 수를 빼면 변수 사이의 거리가 나온다
- 뺏을때 68이란 숫자가 나오는데 이것은 16진수이기 때문에 10진수로 변환하면 104이다