반응형

IDA로 우선까보자

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s1[9]; // [rsp+6h] [rbp-3Ah] BYREF
  char s[9]; // [rsp+Fh] [rbp-31h] BYREF
  unsigned int v6; // [rsp+18h] [rbp-28h] BYREF
  unsigned int v7; // [rsp+1Ch] [rbp-24h] BYREF
  char *s2; // [rsp+20h] [rbp-20h]
  int fd; // [rsp+2Ch] [rbp-14h]
  void *buf; // [rsp+30h] [rbp-10h]
  unsigned int v11; // [rsp+38h] [rbp-8h]
  int i; // [rsp+3Ch] [rbp-4h]

  v7 = 0;
  v6 = 0;
  v11 = 0;
  initialize(argc, argv, envp);
  buf = malloc(0x45uLL);
  fd = open("./flag", 0);
  read(fd, buf, 0x45uLL);
  close(fd);
  get_rand_num(&v6);
  printf("Random number: %#x\n", v6);
  printf("Input? ");
  __isoc99_scanf("%d", &v7);
  v11 = v6 ^ v7;
  snprintf(s, 9uLL, "%08x", v6 ^ v7);
  for ( i = 0; i <= 7; ++i )
    s1[i] = s[7 - i];
  printf("Result: %s\n", s1);
  s2 = "a0b4c1d7";
  if ( !strcmp(s1, "a0b4c1d7") )
  {
    puts("Congrats!");
    puts((const char *)buf);
  }
  else
  {
    puts("Try again");
  }
  return 0;
}

 

1. get_rand_num()에 의해 난수를 생성하고 생성된 난수를 16진수로 출력

2. Input? 이후에 사용자에게 입력받음

3. 입력받은 정수를 난수와 XOR연산을 수행한다.

4. 결과를 8자리 16진수형태의 문자열로 변환하여 저장

5. 저장한 문자열을 역순으로 읽고, a0b4c1d7과 비교한다.

 

 

cf.

argc: 명령줄에 전달된 인자의 갯수(임수 값을 가지지 않음)

argv: 인자의 내용이 저장되는 포인터형 배열

envp: 인자 값 중 환경변수 값이 들어가는 포인터형 배열

-예시-

code

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("%d\n", argc);
    printf("%s\n", argv[0]);
    printf("%s\n", argv[1]);
    return 0;
}

 

 

 

exploit code

from pwn import *

context.log_level = "DEBUG"
p = remote("host3.dreamhack.games", 10336)

p.recvuntil("number: ")

rand_num = p.recvn(10)
rand_num = int(rand_num, 16)  ^ 0x7d1c4b0a
rand_num = str(rand_num)

p.sendlineafter("Input? ", rand_num)

p.interactive()

반응형

'wargame' 카테고리의 다른 글

likeb64  (0) 2024.03.15
bypassIF  (0) 2024.03.10
Broken Buffalo Wings  (0) 2023.09.10
LoS - zombie assassin  (0) 2023.08.27
phpreg  (0) 2023.08.27
반응형

Kernel 내에서의 JIT compiler는 eBPF code를 machine code로 변환시켜주는 역할을 한다.

이는 eBPF의 장점 중 하나인 kernel을 새로 build하지 않고도 kernel code를 수행하게 하도록 도와주며, performance를 향상시킨다.

 

-Compile-

 

https://www.usenix.org/sites/default/files/conference/protected-files/osdi20_slides_nelson.pdf

상기의 사진은 BPF program의 compile과정을 설명한다.

1. BPF program을 kernel내에 주입

2. BPF safety checker(verifier.c 수행)가 해당 code안전한지 여부(ex. infinite loop)를 확인

3. JIT compiler가 machine code로 변환

 

-Runtime-

https://www.usenix.org/sites/default/files/conference/protected-files/osdi20_slides_nelson.pdf

runtime시, 해당 code는 kernel function처럼 동작하며,

return value, memory accesses, function calls를 통하여 kernel과 소통한다.

 

아래의 글은 JIT관련하여 https://sanjit-bhat.github.io/assets/pdf/ebpf-verifier-range-analysis22.pdf의 Jitterbug에 관해 알아보다가 산으로 왔다... JIT관련 정리는 추후에 다시..

 

하지만, 꼭 알아줬으면 하는 내용이다.

아래의 내용은 BPF의 verifier에서 boundary check에 연관되는 개념이기도 하다.(아직 위의 pdf다 못보고 이 글을 씀...)

=============================

이해를 위한 기본 식

SAT(boolean SATisfiability problem)

: 어떠한 논리식이 참인 결과를 찾는 것

satisfiable하다 == 어떠한 논리식을 참으로 만드는 assignment가 1개 이상 존재한다.(assignment: 값 대입/할당)

ex.

 

unsatisfiable하다 == 어떠한 논리식을 참으로 만드는 assignment가 1개 이상 존재하지 않는다.

ex. x and ~x가 참을 만족하는 식이 있을 수 없다.(하단의 사진 참고)

 

SAT solver: SAT문제를 풀어주는 프로그램. 단, 모든 형태의 input을 허용하지 않는다.

input으로 CNF formular를 만족하여 들어온 것들만 풀어준다.

=================================

CNF(Conjunctive Normal From)란,

: clause안에 연산자가 무조건 or만 있는 것, clause를 묶는 것은 무조건 and

ex.

DNF(Disjunctive Normal Form)은 CNF의 역

ex.

cf. Conjuction == or

==================================

output은 그 논리식이 satisfiable하다면, satisfiable과 assignment하나를 같이 출력한다.(여러개가 있더라도 랜덤한 하나의 assignment를 출력한다)

만약, 논리식이 unsatisfiable하다면, unsatisfiable을 출력한다.

ex. 

output

ref. https://microsoft.github.io/z3guide/docs/logic/basiccommands/ 

 

SMT(Satisfiability Modulo Theory)

: SAT과 theory의 결합

theory의 대표적 예시 Linear Real Arithmetic

theory 의 ex.

p = x + y < 10

q = x * 3y - 10 <= 30

r = y + 7 <= 15

 

 

SMT solver는 상기의 식을 SAT처럼 참 거짓을 판별한다. (software 검증에도 사용된다)

 

SMT solver로 문제를 풀 때, 내부적인 동작

1. 각각의 부등식을 SAT처럼 p, q, r로 변환

2. DPLL알고리즘으로 이를 푼다.

2-1. if unsatisfiable이면, unsatisfiable하다고 출력

3. satisfiable하다면, 그 식이 theory의 관점에서도 satisfiable한지 확인한다.(아래의 경우와 같은 예시로 인하여)

부등식일 경우 만족하는 값 UNSAT, 아닐 경우는 SAT

3-1. if satisfiable하다면, satisfiable하다고 출력

3-2. unsatisfiable하다면, DPLL알고리즘을 다시 수행하는데, unsatisfiable한 경우의 수를 제외하도록 수식을 추가한 후 수행한다.

 

-DPLL-

http://rosaec.snu.ac.kr/meet/file/20110626o.pdf

 

-ref-

chapter 4를 메인, sub로는 chapter 6를 참고

https://arxiv.org/abs/2109.10317

반응형

'ebpf' 카테고리의 다른 글

Troubleshooting - learning eBPF  (0) 2024.01.01
JIT for BPF  (0) 2023.09.21
Buzzer(eBPF fuzzer) build  (0) 2023.08.11
eBPF references - Blackhat  (0) 2023.08.06
O’Reilly Report What is eBPF? - tutorial 4  (0) 2023.07.21

반응형

...??????

전혀 접근 방법에 대해서 모르다가 이게 맞나 싶을 정도로 당황스러웠다.

 

상기의 discription을 보고 어디에서 패치가 이루어졌는가 찾아 보았다.

파일의 크기가 다르길래 바로 확인해 보았더니 패치된 파일에는 존재하지 않는 부분이 존재한다.

            location ~ /flag.txt {
                deny all;
                return 403;
            }

이게 있는걸 보아하니... flag.txt경로로 이동하면 플래그가 보이나 싶어서 이동해보니...

..??????????

이 언인텐 풀이로 인하여 문제가 level 1인 것 같다

반응형

'wargame' 카테고리의 다른 글

bypassIF  (0) 2024.03.10
simple-operation  (0) 2023.09.18
LoS - zombie assassin  (0) 2023.08.27
phpreg  (0) 2023.08.27
type confusion  (0) 2023.08.27
반응형

CS에 대해 공부하던 중 주어진 code에 의구심을 품게된 부분이 있어 알아보았습니다.

 

자료형 크기 확인(sizeof)

code

#include <stdio.h>

int main() {
        printf("Size of char: %zu bytes\n", sizeof(char));
        printf("Size of short: %zu bytes\n", sizeof(short));
        printf("Size of int: %zu bytes\n", sizeof(int));
        printf("Size of long: %zu bytes\n", sizeof(long));
        printf("Size of long long: %zu bytes\n", sizeof(long long));
        printf("Size of float: %zu bytes\n", sizeof(float));
        printf("Size of double: %zu bytes\n", sizeof(double));
        printf("Size of long double: %zu bytes\n", sizeof(long double));
        printf("Size of pointer: %zu bytes\n", sizeof(void*));
        return 0;
}

이때, %u가 아닌 %zu를 사용하는 이유는?

A: 우선, sizeof()의 경우 크기를 나타내는 함수 이므로, 양수이다. 이 말인 즉슨 unsigned를 사용하는 것이다.

여기서 근데 unsigned에 대한 type specifier는 %u이고, size_t의 경우는 %zu이다.

 

그렇다면 왜 %zu일까... 구글링 결과 %d를 사용하는 경우도 있고, %u를 사용하는 경우도 있긴했다.

아마 코드의 이식성으로 인하여 사용한 것이 아닐까 싶다...! 더하여, size_t는 unsigned int와 같은 의미이기에 혼용가능한 것 같다.

%u는 32bit냐 64bit냐에 따라 변화가 있을수도 있다고 한다.

 

[+] 공식 문서들을 참고해보았다. 내 예상이 얼추 들어맞은 것 같다만.. 

우선, sizeof()로 인해 %zu를 쓴다기보단, printf()에서 %zu로 쓰도록 C99에 나와있는 것 같다.(이부분은 찾지 못함 ㅠ)

그리고 이전에는 %zu와 %iu 로 나뉘어 msvc에서는 %iu, gcc는 %zu로 사용하였지만 이는 오래전 이야기라고 한다.

https://stackoverflow.com/questions/2524611/how-can-one-print-a-size-t-variable-portably-using-the-printf-family

https://stackoverflow.com/questions/15610053/correct-printf-format-specifier-for-size-t-zu-or-iu

 

[+] %zu대신 %u를 써야하는 이유는 이식성 때문이 맞다. 이는 size_t에 대한 공식 문서와 아래의 블로그를 참고하면 이해하는데에 훨씬 도움이 될것이라 여겨진다.

https://en.cppreference.com/w/c/types/size_t

https://en.cppreference.com/w/cpp/language/sizeof

https://blog.naver.com/oxcow119/220550770300

말이 두서없이 쓰였지만.. 아래의 링크와 위의 말들을 종합해서 이해하는 데에 도움이 되었으면 한다.

그리고 덕분에 size_t가 loop에 의해 메모리나 문자열의 길이를 구한다는 사실을 알게되었다.

또한 unsigned long은 사실 %lu라는 형식 지정자가 있으나, 본 실습의 목적은 sizeof()에 의해 size_t로 출력하는 것이므로 %zu가 권장되는 형식지정자이다. 이 부분 역시 호환성으로 인해 %zu가 권장되는거다!

 

결국 컴퓨터를 배울때마다 항상 중요시되는 호환성! 편의성! 요놈들이 진짜 중요한거다

요놈들에 대해서도 왜? 호환성이  야무져? 이게 왜 편해? 라는데 진짜 그리고 파도파도 이해가 안되면... 앨런 튜링센세를 뵙고오던..C contributer를 뵙고오던...그냥 받아들이던지.. 하는게 답인거 같다ㅠ

 

 

====================

이하의 내용은 간단한 실습들입니다.

 

overflow 재현

code

#include <stdio.h>
#include <limits.h>

int main(){
        char value = CHAR_MAX;
        printf("Original value: %d\n", value);

        value = value+1;
        printf("Value after adding 1: %d\n", value);

        return 0;
}

result

그렇다면 underflow로 해보자!

code

#include <stdio.h>
#include <limits.h>

int main(){
        char value = CHAR_MIN;
        printf("Original value: %d\n", value);

        value = value-1;
        printf("Value after subtracting 1: %d\n", value);

        return 0;
}

result

====================

cf.

gcc -o main main.c -g //디버깅 심볼 포함

일반적으로는 분석의 방해를 위하여 디버깅 심볼을 포함시키지 않는다.

디버깅 심볼을 날릴 시, IDA등의 decompiler로 보기에 난해하다..!!!

(gdb) b main //중단점 설정
(gdb) r //함수를 만날 경우 내불로 들어가지 않고 실행됨
(gdb) n //다음 줄 실행
(gdb) p value // p[변수명] 변수값 출력
(gdb) p/t value // p/[출력형식][변수명]: 출력형식에 맞추어 변수값 출력

==================

특정 위치의 비트를 끄는 c언어 프로그램 작성후 확인 실습

 

1. 특정 비트만큼 1을 시프트한다 (1 << position)

2. 모든 비를 NOT을 활용하여 반전 시킨다.

3. AND연산을 수행함으로써 특정 비트를 끌 수 있다.

 

Answer

#include <stdio.h>

int is_bit_set(unsigned char value, int position) {
        return (value&(1 << position)) != 0;
}

unsigned char set_bit(unsigned char value, int position) {
        return value | ( 1 << position);
}

unsigned char clear_bit(unsigned char value, int position) {
        return  value & ~( 1 << position);
}

int main() {
        unsigned char value = 0b00001000;

        if(is_bit_set(value, 3)) {
                printf("3rd bit is set!\n");
        }
        else {
                printf("3rd bit is not set!\n");
        }

        value = set_bit(value, 2);
        printf("Value after setting 2nd bit: %d\n", value);

        value = clear_bit(value, 2);
        printf("Value after setting 2nd bit: %d\n", value);


        return 0;
}

사용자가 position을 입력받도록 하는 code

#include <stdio.h>

int is_bit_set(unsigned char value, int position) {
        return (value&(1 << position)) != 0;
}

unsigned char set_bit(unsigned char value, int position) {
        return value | ( 1 << position);
}

unsigned char clear_bit(unsigned char value, int position) {
        return  value & ~( 1 << position);
}

int main() {
        unsigned char value = 0b00001000;
        int position = 0;

        if(is_bit_set(value, 3)) {
                printf("3rd bit is set!\n");
        }
        else {
                printf("3rd bit is not set!\n");
        }

        printf("input the position: ");
        scanf("%d", &position);

        value = set_bit(value, position);
        printf("Value after setting 2nd bit: %d\n", value);

        value = clear_bit(value, position);
        printf("Value after setting 2nd bit: %d\n", value);

		return 0;
}

 

=======================

c언어가 기계어가 되는 과정

 

헤더파일(*.h) + 소스코드(*.c) --(pre processing)--> 전처리된 소스코드 파일(*.i) ----(compile)----> 어셈블리어 파일(*.s)

----(assembly)---> 오프젝트파일 (*.o)들 + 라이브러리(*.a, *so) -----(linking)---> 실행파일

기본 코드로 실습

#include <stdio.h>

int main() {
        printf("Hello world!");
        return 0;
}

gcc -E hello.c -o hello.i

gcc -S hello.c -o hello.s   (어셈블리어 확인가능)

gcc -c hello.c -o hello.o  (readelf로 확인)

object file: 소스코드가 컴파일된 후의 중간 결과물, linker에 의해 실행 가능한 바이너리나 라이브러리로 만들어지기 전의 형태

 

특징

1. 바이너리 형태, but 이 파일 자체로는 실행 불가능하며, 다른 오브젝트 파일이나 라이브러리와 링크되어야 실행 가능.

2. 재배치 가능, 다른 object file이나 라이브러리와 링크되어 완전한 프로그램 형성.

3. 심볼 테이블 포함

4. 특정 architecture, OS, compiler에 따라 다르게 생성될 수 있음.

 

 

readelf, objdump, 010에디터 등으로 확인가능

아래의 화면은 HxD로 확인한 결과

 

gcc hello.o -o main

cf. 각단계의 파일을 모두 비교했을 시 과정에 의해 사이즈가 늘어났다가 줄어든다.

 

 

반응형

'System Hacking' 카테고리의 다른 글

heap overlapping  (0) 2024.05.09
pwnable Docker file 세팅 - 드림핵 참고  (0) 2024.02.12
pwnable.kr - flag  (0) 2023.09.10
basic_heap_overflow  (0) 2023.08.22
Mitigation  (0) 2023.01.17
반응형

후하..첨보는게 또 나왔다.

우선 아래와 같이 나온다.

문제를 한번 받아보자

wget으로~~~~~~~~~~~

 

실행권한을 주고 실행시켜보면?

결국은 strcpy로 복사해온다는거 같은디.... 까봐야지 알거같다.

 

음...아무것도 안보인다.

ida로 확인해보아도 뭘 볼수 없다ㅠ

readelf나 file 명령으로도 뭔가를 얻을 순 없었다.

호옥시나 뭔가 있나해서 HxD로 한번 까봤다.

음? 뭔가 한번씩 까보던 ELF파일과는 다르다.

 

UPK로 패킹(?)된 파일이었다 ㄷㄷ

그리하여 검색해보니 아래와 같이 나왔다.

https://reverseengineering.stackexchange.com/questions/11486/how-to-unpack-manually-an-upx-packed-elf-file

 

How to unpack manually an upx packed elf file

I am trying to learn to manually unpack an upx packed elf file. The examples I have found are for Windows, mostly with Ollydbg, and as I see the first step is to look for pushad and popad instructi...

reverseengineering.stackexchange.com

해보자

sudo apt install upx

upx -d -o un_flag flag

이제 다시 gdb로 ㄱㄱ

packing이 풀리니 주르르르를륵 나온다 ㅋㅋ

 

disas main을 수행해보면, main+32에서 flag가 rdx에 담기는 것을 볼 수 있다.

그렇다면! main+39즈음에 bp를 걸고 확인하자!

 

 

flag가 보인다!

반응형

'System Hacking' 카테고리의 다른 글

pwnable Docker file 세팅 - 드림핵 참고  (0) 2024.02.12
computer structure  (0) 2023.09.10
basic_heap_overflow  (0) 2023.08.22
Mitigation  (0) 2023.01.17
Stack Canary  (0) 2022.11.25
반응형

처음 접속시 화면이다.

제출해보면, your not admin이라고 나온다.

우선적으로 sql injection을 시도하려했는데, 입력받는 공간이 정확히 5이다.

injection을 위하여 length를 50으로 늘려주고, 기본 쿼리를 넣어보았다.

 

ez~

또 다른 풀이는 제출시, url 에 박히는 것을 활용하면된다.

https://webhacking.kr/challenge/js-6/?id=admin

 

admin자리에 admin'--를 넣어주어도 풀린다.

 

반응형

'webhacking.kr' 카테고리의 다른 글

webhacking.kr [old-38]  (0) 2023.07.16
webhacking.kr [old-36]  (0) 2023.07.15
webhacking.kr [old-27]  (0) 2023.07.15
webhacking.kr [old-25]  (0) 2023.07.15
webhacking.kr [old-27]  (0) 2023.07.15
반응형

이전의 succubus문제와 유사하게 풀면된다.

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect();
  $_GET['id'] = strrev(addslashes($_GET['id']));
  $_GET['pw'] = strrev(addslashes($_GET['pw']));
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_zombie_assassin where id='{$_GET[id]}' and pw='{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) solve("zombie_assassin"); 
  highlight_file(__FILE__); 
?>

여기서 알아야할 함수는 두가지이다.

addslashes : ', " , %00(null) 뒤에 역슬래시를 추가한다.

strrev() : 문자열을 반대순서로 입력한다.

ex. strrev(test) -> tset

 

일부러 addslashes를 이용하는 payload를 구성하면 아래와 같다.

id="&pw=or 1=1%23

 

이제 입력하기 위해 역순으로 만들어준다. 이 때, %23역시 32%로 만들어주면 #으로 인식하지 못하기에 %23은 그대로 입력해주어야한다.

그리하여 최종적인 payload는 아래와 같다.

?id="&pw=%231=1%20ro

 이렇게 보내면, highlight친 부분이 문자열로 처리되기에 뚫리는 것이다.

반응형

'wargame' 카테고리의 다른 글

simple-operation  (0) 2023.09.18
Broken Buffalo Wings  (0) 2023.09.10
phpreg  (0) 2023.08.27
type confusion  (0) 2023.08.27
tmitter  (0) 2023.08.26

+ Recent posts