使用Go语言 在windows下 实现隐藏进程命令行参数 保护密码等数据

C语言在unix下可以通过直接覆写argv的方式隐藏参数,但是在windows下由于win32 api的限制,获取到的参数是一串连续的字符串,在C语言的main函数调用之前已经由C标准库实现了分割,导致直接修改argv并不能实现隐藏参数的目的。

但是,我们可以利用golang封装的syscall.GetCommandLine()直接拿到该处内存的切片,从而可以方便地进行修改。当然,C语言通过系统调用同样也可以实现这点。

感谢@wdvxdr1123对本方法在可行性方面提出的建议

直接使用

如果您不关心实现,为方便起见,本方法已经封装成了package,使用也很简单,只需要像下面这样写即可。

import para "github.com/fumiama/go-hide-param"
// This will hide os.Args[index]
para.Hide(index)

实现代码

//go:build windows
// +build windows

package gohideparam

import (
	"os"
	"syscall"
	"unsafe"
)

// Slice is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
//
// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
// data it references will not be garbage collected.
type Slice struct {
	Data unsafe.Pointer
	Len  int
	Cap  int
}

// readNextArg splits command line string cmd into next
// argument and command line remainder.
func readNextArg(cmd *[]uint16, is2erase bool) {
	var inquote bool
	var nslash int
	for ; len(*cmd) > 0; (*cmd) = (*cmd)[1:] {
		switch (*cmd)[0] {
		case uint16(' '), uint16('\t'):
			if !inquote {
				return
			}
		case uint16('"'):
			if nslash%2 == 0 {
				// use "Prior to 2008" rule from
				// http://daviddeley.com/autohotkey/parameters/parameters.htm
				// section 5.2 to deal with double double quotes
				if inquote && len(*cmd) > 1 && (*cmd)[1] == uint16('"') {
					*cmd = (*cmd)[1:]
				}
				inquote = !inquote
			}
			nslash = 0
			continue
		case uint16('\\'):
			nslash++
			if is2erase {
				(*cmd)[0] = uint16('*')
			}
			continue
		default:
			if is2erase {
				(*cmd)[0] = uint16('*')
			}
		}
		nslash = 0
	}
}

func eraseCommandLine(cmd *[]uint16, pos uint) {
	var p uint
	for len(*cmd) > 0 && p <= pos {
		if (*cmd)[0] == uint16(' ') || (*cmd)[0] == uint16('\t') {
			(*cmd) = (*cmd)[1:]
			continue
		}
		readNextArg(cmd, p == pos)
		p++
	}
}

func utf16PtrToSlice(p *uint16) []uint16 {
	if p == nil {
		return nil
	}
	// Find NUL terminator.
	end := unsafe.Pointer(p)
	n := 0
	for *(*uint16)(end) != 0 {
		end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
		n++
	}
	// Turn *uint16 into []uint16.
	var s []uint16
	hdr := (*Slice)(unsafe.Pointer(&s))
	hdr.Data = unsafe.Pointer(p)
	hdr.Cap = n
	hdr.Len = n
	return s
}

func Hide(position int) {
	if position > 0 && position < len(os.Args) {
		cmd := utf16PtrToSlice(syscall.GetCommandLine())
		eraseCommandLine(&cmd, uint(position))
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值