doudu3961 2018-10-04 16:38
浏览 237
已采纳

禁用Go编译程序的堆栈保护

I want to disable the stack protection for my Go program. I'm trying to simulate a vulnerable C library and want to pivot into the Go code from there. However, I can't seem to find the right flags to disable the stack smashing detection.

Here is my go code:

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")
}

and here is my c library code:

// #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!
", r, buf);
    return;
}

I compile with go build -a poc.go.

As you can see, I already added some CFLAGS instructions at the beginning of my C library, but they don't seem to help. Previously I tried adding them via the -gcflags switch in my compilation command, but that was fruitless as well. Everytime I try to attack my program with a 300*A string, it is being detected:

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 
[...]

Checking the file with GDB also tells me the option is still active.. Could you please point me to some hints as to what I'm doing wrong or what flags I should use to disable this feature?

Thanks so much!

  • 写回答

1条回答 默认 最新

  • dongxie2756 2018-10-04 23:18
    关注

    Start with the Go cgo command documentation.

    Command cgo

    Using cgo with the go command

    To use cgo write normal Go code that imports a pseudo-package "C". The Go code can then refer to types such as C.size_t, variables such as C.stdout, or functions such as C.putchar.

    If the import of "C" is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package. For example:

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

    The preamble may contain any C code, including function and variable declarations and definitions. These may then be referred to from Go code as though they were defined in the package "C". All names declared in the preamble may be used, even if they start with a lower-case letter. Exception: static variables in the preamble may not be referenced from Go code; static functions are permitted.

    See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See "C? Go? Cgo!" for an introduction to using cgo: https://golang.org/doc/articles/c_go_cgo.html.

    CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS and LDFLAGS may be defined with pseudo #cgo directives within these comments to tweak the behavior of the C, C++ or Fortran compiler. Values defined in multiple directives are concatenated together. The directive can include a list of build constraints limiting its effect to systems satisfying one of the constraints (see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax). For example:

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

    In particular:

    To use cgo write normal Go code that imports a pseudo-package "C".

    If the import of "C" is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package.

    CFLAGS may be defined with pseudo #cgo directives within these comments to tweak the behavior of the C compiler.

    For your example:

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

    Output (no stack smashing detected):

    $ 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!
    ", r, buf);
        return;
    }
    

    Without -fno-stack-protector:

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

    Output (stack smashing detected):

    $ 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
    $
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况