Отключить защиту стека для скомпилированной программы go - PullRequest
0 голосов
/ 04 октября 2018

Я хочу отключить защиту стека для моей программы Go.Я пытаюсь смоделировать уязвимую библиотеку C и хочу развернуть код Go оттуда.Тем не менее, я не могу найти правильные флаги, чтобы отключить обнаружение разрушения стека.

Вот мой код go:

package main

import "os"
import "fmt"

/*
#include "test.h"
*/
import "C"

func main() {
    if (len(os.Args) >= 2){
    argsWithoutProg := os.Args[1:]
        if (argsWithoutProg[0] == "admin") {
            secret();
        }
    } else {
        regular()
    }
}

func regular() {
    fmt.Println("Go: BORING")
    C.hackme()
}

func secret() {
    fmt.Println("Go: SECRET FUNC")
}

, а вот мой код библиотеки c:

// #cgo CFLAGS: -g -O3 -fno-stack-protector
#include <stdint.h>
#include <stdio.h>

void hackme();

// this function is vulnerable and is used as an entrypoint to the go part
void hackme() {
    char buf[3];
    int r;
    r = read(0, buf, 300);
    printf("C: %d bytes read. Content: %s!\n", r, buf);
    return;
}

Я компилирую с go build -a poc.go.

Как видите, я уже добавил несколько инструкций CFLAGS в начале своей библиотеки C, но, похоже, они не помогают.Ранее я пытался добавить их с помощью ключа -gcflags в моей команде компиляции, но это также было бесполезно.Каждый раз, когда я пытаюсь атаковать мою программу с помощью строки 300 * A, она обнаруживается:

Go: BORING
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
C: 300 bytes read. Content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!
*** stack smashing detected ***: <unknown> terminated
SIGABRT: abort
PC=0x7fd263dcee97 m=0 sigcode=18446744073709551610

goroutine 0 [idle]:
runtime: unknown pc 0x7fd263dcee97
stack: frame={sp:0x7ffda3507600, fp:0x0} stack=[0x7ffda2d08ad0,0x7ffda3507b00)
00007ffda3507500:  00007fd200000008  00007fd200000000
00007ffda3507510:  00007ffda3507610  0000000000000003 
[...]

Проверка файла с помощью GDB также показывает, что опция все еще активна. Не могли бы вы указать мне на некоторыенамеки на то, что я делаю неправильно или какие флаги мне следует использовать, чтобы отключить эту функцию?

Большое спасибо!

1 Ответ

0 голосов
/ 05 октября 2018

Начните с документации команды Go cgo.

Команда cgo

Использование cgo с командой go

Чтобы использовать cgo, напишите обычный код Go, который импортирует псевдопакет "C".Затем код Go может ссылаться на такие типы, как C.size_t, переменные, такие как C.stdout, или функции, такие как C.putchar.

Если импорту «C» предшествует комментарий, тоКомментарий, называемый преамбулой, используется в качестве заголовка при компиляции C-частей пакета.Например:

// #include <stdio.h>
// #include <errno.h>
import "C"

Преамбула может содержать любой код на C, включая объявления и определения функций и переменных.Затем они могут быть переданы из кода Go, как если бы они были определены в пакете «C».Могут использоваться все имена, объявленные в преамбуле, даже если они начинаются со строчной буквы.Исключение: на статические переменные в преамбуле нельзя ссылаться из кода Go;разрешены статические функции.

См. примеры $ GOROOT / misc / cgo / stdio и $ GOROOT / misc / cgo / gmp.Смотрите "C? Go? Cgo!"для введения в использование cgo: https://golang.org/doc/articles/c_go_cgo.html.

CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS и LDFLAGS могут быть определены с помощью директив pseudo #cgo в этих комментариях, чтобы настроить поведение компилятора C, C ++ или Fortran.Значения, определенные в нескольких директивах, объединяются вместе.Директива может включать список ограничений сборки, ограничивающих ее действие системами, удовлетворяющими одному из ограничений (подробности о синтаксисе ограничений см. В https://golang.org/pkg/go/build/#hdr-Build_Constraints).Например:

// #cgo CFLAGS: -DPNG_DEBUG=1
// #cgo amd64 386 CFLAGS: -DX86=1
// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"

В частности:

Чтобы использовать cgo, напишите обычный код Go, который импортирует псевдопакет "C".

Если импорту "C" непосредственно предшествует комментарий, этот комментарий, называемый преамбулой, используется в качестве заголовка при компиляции частей пакета C. Все значения

CFLAGS могут быть определены с помощью псевдоДирективы #cgo в этих комментариях настраивают поведение компилятора C.

Для вашего примера:

/*
#cgo CFLAGS: -g -O3 -fno-stack-protector
#include "test.h"
*/
import "C"

Вывод (не обнаружено разрушения стека):

$ go build -a poc.go && ./poc
Go: BORING
AAAAAAAAAAAAAAA
C: 16 bytes read. Content: AAAAAAAAAAAAAAA
!
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0xa41414141 pc=0xa41414141]

runtime stack:
runtime.throw(0x4bb802, 0x2a)
    /home/peter/go/src/runtime/panic.go:608 +0x72
runtime.sigpanic()
    /home/peter/go/src/runtime/signal_unix.go:374 +0x2ec

goroutine 1 [syscall]:
runtime.cgocall(0x484e90, 0xc000052f38, 0x0)
    /home/peter/go/src/runtime/cgocall.go:128 +0x5b fp=0xc000052f08 sp=0xc000052ed0 pc=0x403deb
main._Cfunc_hackme()
    _cgo_gotypes.go:41 +0x41 fp=0xc000052f38 sp=0xc000052f08 pc=0x484c51
main.regular()
    /home/peter/gopath/src/poc/poc.go:25 +0x62 fp=0xc000052f88 sp=0xc000052f38 pc=0x484d52
main.main()
    /home/peter/gopath/src/poc/poc.go:19 +0x65 fp=0xc000052f98 sp=0xc000052f88 pc=0x484cd5
runtime.main()
    /home/peter/go/src/runtime/proc.go:201 +0x1ec fp=0xc000052fe0 sp=0xc000052f98 pc=0x42928c
runtime.goexit()
    /home/peter/go/src/runtime/asm_amd64.s:1340 +0x1 fp=0xc000052fe8 sp=0xc000052fe0 pc=0x450cd1
$

poc.go:

package main

import "os"
import "fmt"

/*
#cgo CFLAGS: -g -O3 -fno-stack-protector
#include "test.h"
*/
import "C"

func main() {
    if (len(os.Args) >= 2){
    argsWithoutProg := os.Args[1:]
        if (argsWithoutProg[0] == "admin") {
            secret();
        }
    } else {
        regular()
    }
}

func regular() {
    fmt.Println("Go: BORING")
    C.hackme()
}

func secret() {
    fmt.Println("Go: SECRET FUNC")
}

test.h:

#include <stdint.h>
#include <stdio.h>

void hackme();

// this function is vulnerable and is used as an entrypoint to the go part
void hackme() {
    char buf[3];
    int r;
    r = read(0, buf, 300);
    printf("C: %d bytes read. Content: %s!\n", r, buf);
    return;
}

Без -fno-stack-protector:

/*
#cgo CFLAGS: -g -O3
#include "test.h"
*/
import "C"

Выход (стекобнаружено разрушение):

$ go build -a poc.go && ./poc
Go: BORING
AAAAAAAAAAAAAAA
C: 16 bytes read. Content: AAAAAAAAAAAAAAA
!
*** stack smashing detected ***: <unknown> terminated
SIGABRT: abort
PC=0x7f1c5323ee97 m=0 sigcode=18446744073709551610
$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...