GTK3 - How to send a window to the background - windows

I am trying to send a window to the background, but SetKeepBelow has no effect on windows. Is there any way to achieve this? I am using golang and gotk3, but I can add additional bindings if needed.
Another option would probably be using this: https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setwindowpos
But I am not sure how exactly, as I can't retrieve the window handle from within gtk.

So, I have found a solution and like mentioned in the comments of the questions, it is hacky! However, I didn't want to leave this unsolved. So what I am doing is using the SetWindowPos function of windows in order to move it on the z axis. However, in order to be able to do so, you first need the pointer to the hWnd, I am retrieving that with FindWindowA which takes a classname and a windowtitle, sicne I don't know the class, I am passing nil. Passing nil causes the function to only search by windowtitle. Ofc this solution only works if your window has a unique title!
package main
import (
"unsafe"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
"golang.org/x/sys/windows"
)
var (
mod = windows.NewLazyDLL("user32.dll")
setWindowPosFunction = mod.NewProc("SetWindowPos")
findWindowFunction = mod.NewProc("FindWindowA")
)
//ToBackground moves the window to the background, preserving its size and position
func ToBackground(hwnd uintptr, gtkWindow *gtk.Window) error {
x, y := gtkWindow.GetPosition()
width, height := gtkWindow.GetSize()
_, _, err := setWindowPosFunction.Call(hwnd, uintptr(1), uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0)
if err != nil && err.Error() == "The operation completed successfully." {
return nil
}
return err
}
func main() {
gtk.Init(nil)
window, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
window.SetTypeHint(gdk.WINDOW_TYPE_HINT_UTILITY)
title := "unique-identifier"
window.SetTitle(title)
window.SetPosition(gtk.WIN_POS_CENTER)
window.ShowAll()
titleAsByteArray := []byte(title)
hwnd, _, windowRetrieveError := findWindowFunction.Call(0, uintptr(unsafe.Pointer(&titleAsByteArray[0])))
if windowRetrieveError != nil && windowRetrieveError.Error() != "The operation completed successfully." {
panic(windowRetrieveError)
}
toBackgroundError := ToBackground(hwnd, window)
if toBackgroundError != nil {
panic(toBackgroundError)
}
gtk.Main()
}

Related

Go: Why do processes/Threads started using Win32API funcs seem to hijack and kill the parent proccess?

Now, the following code does what it's supposed to do, load calc.exe to memory and execute it, it does that fine.
I've stitched together this code to show CreateThread() Killing my program's execution flow right before popping calc.exe, Simply after CreateThread.Call(), No other instructions are executed after it
And i believe this isn't a memory allocation issue, because if i wrap CreateThread() in a goroutine (go runThread() ) It executes a few loop cycles before popping calc.exe
package main
import (
"fmt"
"encoding/hex"
"golang.org/x/sys/windows"
"log"
"unsafe"
)
func main(){
RunCreateThread()
for {
fmt.Println("Running infinitely")
}
}
func RunCreateThread() {
//calc.exe HEX
shellcode, _ :=hex.DecodeString("fc4883e4f0e8c0000000415141505251564831d265488b5260488b5218488b5220488b7250480fb74a4a4d31c94831c0ac3c617c022c2041c1c90d4101c1e2ed524151488b52208b423c4801d08b80880000004885c074674801d0508b4818448b40204901d0e35648ffc9418b34884801d64d31c94831c0ac41c1c90d4101c138e075f14c034c24084539d175d858448b40244901d066418b0c48448b401c4901d0418b04884801d0415841585e595a41584159415a4883ec204152ffe05841595a488b12e957ffffff5d48ba0100000000000000488d8d0101000041ba318b6f87ffd5bbf0b5a25641baa695bd9dffd54883c4283c067c0a80fbe07505bb4713726f6a00594189daffd563616c632e65786500")
addr, errVirtualAlloc := windows.VirtualAlloc(uintptr(0), uintptr(len(shellcode)), windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
if errVirtualAlloc != nil {11
log.Fatal(fmt.Sprintf("[!]Error calling VirtualAlloc:\r\n%s", errVirtualAlloc.Error()))
}
ntdll := windows.NewLazySystemDLL("ntdll.dll")
RtlCopyMemory := ntdll.NewProc("RtlCopyMemory")
_, _, errRtlCopyMemory := RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&shellcode[0])), uintptr(len(shellcode)))
if errRtlCopyMemory != nil && errRtlCopyMemory.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("[!]Error calling RtlCopyMemory:\r\n%s", errRtlCopyMemory.Error()))
}
var oldProtect uint32
errVirtualProtect := windows.VirtualProtect(addr, uintptr(len(shellcode)), windows.PAGE_EXECUTE_READ, &oldProtect)
if errVirtualProtect != nil {
log.Fatal(fmt.Sprintf("[!]Error calling VirtualProtect:\r\n%s", errVirtualProtect.Error()))
}
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
CreateThread := kernel32.NewProc("CreateThread")
thread, _, errCreateThread := CreateThread.Call(0, 0, addr, uintptr(0), 0, 0)
if errCreateThread != nil && errCreateThread.Error() != "The operation completed successfully." {
log.Fatal(fmt.Sprintf("[!]Error calling CreateThread:\r\n%s", errCreateThread.Error()))
}
_, _ = windows.WaitForSingleObject(windows.Handle(thread), 0xFFFFFFFF)
}
I'm curious to why this happens?
As it turns out, it was indeed a shellcode issue, The code calls Fine, I didn't know that msfvenom payloads often mess with their host callers in weird ways sometimes.

Start a child process with ShellExecute and reuse parent console with AttachConsole

I have a problem which seems rather simple to me, but I cannot make it work properly on Windows:
I'm running a console program in Go, and some commands will need to run as an elevated process
That's how I restart my console program as an elevated user, and it works fine:
func RunElevated() error {
verb := "runas"
exe, _ := os.Executable()
cwd, _ := os.Getwd()
args := "--as-child " + strings.Join(os.Args[1:], " ")
verbPtr, _ := syscall.UTF16PtrFromString(verb)
exePtr, _ := syscall.UTF16PtrFromString(exe)
cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
argPtr, _ := syscall.UTF16PtrFromString(args)
var showCmd int32 = 1 //SW_NORMAL
// also tried with zero as first parameter; I think it's about GUI window, not console?
err := windows.ShellExecute(GetConsoleWindow(), verbPtr, exePtr, argPtr, cwdPtr, showCmd)
if err != nil {
return err
}
return nil
}
// GetConsoleWindow from windows kernel32 API
func GetConsoleWindow() windows.Handle {
getConsoleWindow := kernel32.NewProc("GetConsoleWindow")
ret, _, _ := getConsoleWindow.Call()
return windows.Handle(ret)
}
... but the problem is that it's starting in a new console window.
I'd like to close it and reattach to the parent one. So here's the code:
const (
ATTACH_PARENT_PROCESS windows.Handle = 0x0ffffffff
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
)
// AttachParentConsole detach from the current console and attach to the parent process console
func AttachParentConsole() error {
err := FreeConsole()
if err != nil {
return err
}
err = AttachConsole(ATTACH_PARENT_PROCESS)
if err != nil {
return err
}
return nil
}
// FreeConsole from windows kernel32 API
func FreeConsole() error {
freeConsole := kernel32.NewProc("FreeConsole")
ret, _, _ := freeConsole.Call()
if ret == 0 {
return syscall.GetLastError()
}
return nil
}
// AttachConsole from windows kernel32 API
func AttachConsole(consoleOwner windows.Handle) error {
attachConsole := kernel32.NewProc("AttachConsole")
ret, _, _ := attachConsole.Call(uintptr(consoleOwner))
if ret == 0 {
return syscall.GetLastError()
}
return nil
}
At that point, Windows seems happy enough: it reports no error, and a flashing console appear and disappear as fast as you can refresh the screen.
I also believe the child command runs fine as it waits from an input from the user - I can see it in still running in the task manager; but nothing is displayed on the parent console.
So I was thinking the go runtime might keep the original handle somewhere? I had a look at the initialisation, and since these files don't exist on Windows I'm thinking they should be magic values for the go runtime:
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
So I tried re-assigning os.Stdout and its friends using the same code in case the "/dev/stdout" would pick up the new console, but no luck here. Still nothing displayed.
Am I missing something or doing something stupid here?
Some help would be much appreciated :)

A go code program failed to run in the background

Go code running in the background
I am a beginner of the go language.
I wrote a small program that made a keyboard sound.
After go build main.go, you can hear the sound of the button in the current shell.
But when running ./main in the background or when re-opening a new shell will not hear the button sound.
This is what I need help with.
package main
import (
"fmt"
"github.com/eiannone/keyboard"
"github.com/faiface/beep"
"github.com/faiface/beep/speaker"
"github.com/faiface/beep/wav"
"os"
"time"
"log"
"path/filepath"
)
func main(){
env:= os.Getenv("HOME")
fmt.Println(env)
err := keyboard.Open()
if err != nil {
panic(err)
}
defer keyboard.Close()
for {
char, key, err := keyboard.GetKey()
if err != nil {
log.Fatal(err)
}else if (key == keyboard.KeyEsc){
break
}
n := int(char)
path := "./wav/*.wav"
fpath,_ := filepath.Glob(path)
name := fpath[n]
f, err := os.Open(name)
if err != nil {
log.Fatal(err)
}
streamer, format, err := wav.Decode(f)
if err != nil {
log.Fatal(err)
}
defer streamer.Close()
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
done := make(chan bool)
speaker.Play(beep.Seq(streamer, beep.Callback(func() {
done <- true
})))
<-done
}
}
I want it to run in the background. I can hear the corresponding sound after pressing the keyboard.
If the program is running in the background it will not get any input from the keyboard.
Also since n depends on user input it would be easy for it to exceed the number of sound files and you would get an index out of bounds error at run-time. You should do something like this:
if fpath, _ := filepath.Glob("./wav/*.wav"); len(fpath) > 0 {
n := int(char)%len(fpath)
name := fpath[n]
...

Capture the space key in Go without following enter

I am looking for a lightweight and in the best case pure go implementation to capture space without a following enter.
I have seen some people using C as extern in Go or termbox. Is there really no other method of capturing every keyboard stroke?
I have already thought about opening the device directly (in Linux) and trying to read from there.
Any advice of how to do this would be great!
Without more information, it's hard to come up with a perfect example of what you're looking for. However, the basic idea is that you need to switch your terminal into raw mode, where input is passed immediately to your application. x/crypto/ssh/terminal is a popular library that provides this functionality:
package main
import (
"fmt"
"os"
"golang.org/x/crypto/ssh/terminal"
)
func main() {
oldState, err := terminal.MakeRaw(0)
if err != nil {
panic(err)
}
defer terminal.Restore(0, oldState)
for {
var oneChar [1]byte
_, err := os.Stdin.Read(oneChar[:])
const ETX = '\x03' // ^C
const EOT = '\x04' // ^D
if err != nil || oneChar[0] == ETX || oneChar[0] == EOT {
break
}
if oneChar[0] == ' ' {
fmt.Println("Space pressed!\r")
break
}
}
}

Convert an image to grayscale in Go

I'm trying to convert an image to grayscale using Go.
I've found the below code, however, I'm struggling to understand it.
It would be extremely helpful if you could explain what each function is doing and where to define the incoming and outgoing file.
package main
import (
"image"
_ "image/jpeg" // Register JPEG format
"image/png" // Register PNG format
"image/color"
"log"
"os"
)
// Converted implements image.Image, so you can
// pretend that it is the converted image.
type Converted struct {
Img image.Image
Mod color.Model
}
// We return the new color model...
func (c *Converted) ColorModel() color.Model{
return c.Mod
}
// ... but the original bounds
func (c *Converted) Bounds() image.Rectangle{
return c.Img.Bounds()
}
// At forwards the call to the original image and
// then asks the color model to convert it.
func (c *Converted) At(x, y int) color.Color{
return c.Mod.Convert(c.Img.At(x,y))
}
func main() {
if len(os.Args) != 3 { log.Fatalln("Needs two arguments")}
infile, err := os.Open(os.Args[1])
if err != nil {
log.Fatalln(err)
}
defer infile.Close()
img, _, err := image.Decode(infile)
if err != nil {
log.Fatalln(err)
}
// Since Converted implements image, this is now a grayscale image
gr := &Converted{img, color.GrayModel}
// Or do something like this to convert it into a black and
// white image.
// bw := []color.Color{color.Black,color.White}
// gr := &Converted{img, color.Palette(bw)}
outfile, err := os.Create(os.Args[2])
if err != nil {
log.Fatalln(err)
}
defer outfile.Close()
png.Encode(outfile,gr)
}
I'm quite new to Go so any suggestions or help would be appreciated.
So as Atomic_alarm pointed out, https://maxhalford.github.io/blog/halftoning-1/ explains how to do this succinctly.
But you're question, if I understand correctly, is about the file opening and creation?
The first step is to use the image package to Decode the opened file into an image.Image struct:
infile, err := os.Open("fullcolor.png")
if err != nil {
return nil, err
}
defer infile.Close()
img, _, err := image.Decode(infile) // img -> image.Image
if err != nil {
return nil, err
}
With this Go image.Image struct, you can convert it to a grayscaled image, image.Gray and then, finally, write or encode the image onto an outgoing file on the disk:
outfile, _ := os.Create("grayscaled.png")
defer outfile.Close()
png.Encode(outfile, grayscaledImage) // grayscaledImage -> image.Gray
Inbetween the infile opening and outfile creating, you have to, of course, convert the image to grayscale. Again, try the link above, and you'll find this function, which takes an image.Image and returns a pointer to a image.Gray:
func rgbaToGray(img image.Image) *image.Gray {
var (
bounds = img.Bounds()
gray = image.NewGray(bounds)
)
for x := 0; x < bounds.Max.X; x++ {
for y := 0; y < bounds.Max.Y; y++ {
var rgba = img.At(x, y)
gray.Set(x, y, rgba)
}
}
return gray
}
Concerning the code you provided (and your comment), you were opening a file with os.Args[1], and creating the file os.Args[2]. os.Args is a slice of arguments passed when running the program, 0 will always be the program itself (main), and whatever follows will with 1, 2, etc. The docs states:
Args hold the command-line arguments, starting with the program name.
var Args []string
so you would run your code above like this:
$ go run main.go infile.png outfile.png
infile.png must to be a file on disk (inside the directory you are running the code from, or the complete path to file).
What I have provide above doesn't use os.Args but rather hard codes the file names into the program.

Resources