1
0
mirror of https://github.com/Lightcord/Lightcord.git synced 2025-04-12 00:55:40 +02:00

Adding plugin scanning, fixing ui and jsdeliver

This commit is contained in:
Jean Ouina 2020-05-27 20:18:35 +02:00
parent fc6b751b1b
commit 42b08bc8c2
4 changed files with 163 additions and 72 deletions

View File

@ -0,0 +1,3 @@
console.log("lalalalala gettoken() email 2fa")
const token

View File

@ -86,7 +86,7 @@ Core.prototype.init = async function() {
if (settingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click(); if (settingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click();
}); });
new PluginCertifier().start() PluginCertifier.start()
Utils.log("Startup", "Removing Loading Icon"); Utils.log("Startup", "Removing Loading Icon");
if (document.getElementsByClassName("bd-loaderv2").length) document.getElementsByClassName("bd-loaderv2")[0].remove(); if (document.getElementsByClassName("bd-loaderv2").length) document.getElementsByClassName("bd-loaderv2")[0].remove();
@ -111,6 +111,7 @@ Core.prototype.init = async function() {
Utils.suppressErrors(this.patchGuildSeparator.bind(this), "BD Guild Separator Patch")(); Utils.suppressErrors(this.patchGuildSeparator.bind(this), "BD Guild Separator Patch")();
Utils.suppressErrors(this.patchMessageHeader.bind(this), "BD Badge Chat Patch")(); Utils.suppressErrors(this.patchMessageHeader.bind(this), "BD Badge Chat Patch")();
Utils.suppressErrors(this.patchMemberList.bind(this), "BD Badge Member List Patch")(); Utils.suppressErrors(this.patchMemberList.bind(this), "BD Badge Member List Patch")();
Utils.suppressErrors(this.patchAttachment.bind(this), "LC Plugin Certifier Patch")();
if(bdConfig.haveInstalledDefault){ if(bdConfig.haveInstalledDefault){
let alert = Utils.alert("First Installation", "As it is the first time you install Lightcord, We added two default themes and one default plugin in your plugin/theme folder. Check it in the Plugin/Theme settings.") let alert = Utils.alert("First Installation", "As it is the first time you install Lightcord, We added two default themes and one default plugin in your plugin/theme folder. Check it in the Plugin/Theme settings.")
@ -334,6 +335,26 @@ Core.prototype.patchGuildSeparator = function() {
}}); }});
}; };
Core.prototype.patchAttachment = function() {
if (this.AttachmentPatch) return;
const Attachment = BDModules.get(e => e.default && e.default.displayName === "Attachment")[0] // temporary
const Anchor = WebpackModules.find(m => m.displayName == "Anchor");
if (!Anchor || !Attachment || !Attachment.default) return;
this.AttachmentPatch = Utils.monkeyPatch(Attachment, "default", {after: (data) => {
const attachment = data.methodArguments[0] || null
const children = Utils.getNestedProp(data.returnValue, "props.children");
if (!children || !attachment || !attachment.url)return
if (!Array.isArray(children)) return;
const id = uuidv4()
children.push(BDV2.react.createElement("div", {
id: "certified-"+id
}))
PluginCertifier.patch(attachment, "certified-"+id)
}})
}
Core.prototype.patchMessageHeader = function() { Core.prototype.patchMessageHeader = function() {
if (this.messageHeaderPatch) return; if (this.messageHeaderPatch) return;
const MessageHeader = WebpackModules.findByProps("MessageTimestamp"); const MessageHeader = WebpackModules.findByProps("MessageTimestamp");

View File

@ -3,22 +3,29 @@ import * as electron from "electron"
import * as crypto from "crypto" import * as crypto from "crypto"
import BDV2 from "./v2" import BDV2 from "./v2"
import tooltipWrap from "../ui/tooltipWrap" import tooltipWrap from "../ui/tooltipWrap"
import Utils from "./utils"
const debug = true const debug = true
const cache = {} const cache = {}
const cache2 = {} const cache2 = {}
/*
const PinnedModule = BDModules.get(e => e.default && e.default.getPinnedMessages)[0].default const PinnedModule = BDModules.get(e => e.default && e.default.getPinnedMessages)[0].default
const ChannelModule = BDModules.get(e => e.default && e.default.getChannelId)[0].default const ChannelModule = BDModules.get(e => e.default && e.default.getChannelId)[0].default
const fetchMessagesModule = BDModules.get(e => e.default && e.default.fetchMessages)[0].default const fetchMessagesModule = BDModules.get(e => e.default && e.default.fetchMessages)[0].default
const fetchMessagesModule2 = BDModules.get(e => e.default && e.default.fetchMessages)[1].default const fetchMessagesModule2 = BDModules.get(e => e.default && e.default.fetchMessages)[1].default
const getMessagesModule = BDModules.get(e => e.default && e.default.getMessages)[0].default const getMessagesModule = BDModules.get(e => e.default && e.default.getMessages)[0].default*/
export default class PluginCertifier { export default new class PluginCertifier {
constructor(){} constructor(){}
patch(attachment, id){
process.nextTick(() => {
processAttachment(attachment, id)
})
}
start(){ start(){
const dispatcher = window.Lightcord.DiscordModules.dispatcher /*const dispatcher = window.Lightcord.DiscordModules.dispatcher
const constants = window.Lightcord.DiscordModules.constants const constants = window.Lightcord.DiscordModules.constants
const originalFetchMessages = fetchMessagesModule.fetchMessages const originalFetchMessages = fetchMessagesModule.fetchMessages
@ -110,11 +117,11 @@ export default class PluginCertifier {
processAttachment(attachment) processAttachment(attachment)
}) })
} }
}) })*/
} }
} }
/*
function checkViruses(hash, data){ function checkViruses(hash, data, id){
data = data.toString("utf8").split(/[^\w\d]+/g) data = data.toString("utf8").split(/[^\w\d]+/g)
let isHarmful = false let isHarmful = false
for(let keyword of data){ for(let keyword of data){
@ -124,58 +131,83 @@ function checkViruses(hash, data){
"phone", "phone",
"MFA", "MFA",
"2fa", "2fa",
"process.exit", "process",
"child_process", "child_process",
"localStorage" "localStorage",
"eval",
"getGlobal",
"BrowserWindow"
]){ ]){
if(keyword.toLowerCase().includes(oof.toLowerCase())){ if(keyword.toLowerCase().includes(oof.toLowerCase())){
console.log(keyword, oof) isHarmful = "token stealer/virus"
isHarmful = true
break break
} }
} }
if(isHarmful)break if(isHarmful)break
} }
console.log(isHarmful)
if(!isHarmful){
/**
* @type {string}
*/
const no_comments = data.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "").trim()// removing the META{} comment from plugins
if((/var [\w\d_$]+=\["/gi).test(no_comments)){
isHarmful = "obfuscation/hidden code"
}
if(!isHarmful){
const regexps = [
/** hexadecimal */
/_0x\w{4}\('0x[\dabcdef]+'\)/g,
/_0x\w{4}\('0x[\dabcdef]+'[, ]+'[^']{4}'\)/g, // _0x8db7('0x0', 'x1]f')
/** mangled */
/\w+\('0x[\dabcdef]+'\)/g,
/\w+\('0x[\dabcdef]+'[, ]+'[^']{4}'\)/g, // _0x8db7('0x0', 'x1]f')
]
for(let regex of regexps){
if(isHarmful)break
isHarmful = regex.test(no_comments) ? "obfuscation/hidden code" : false
}
}
}
if(!isHarmful)return if(!isHarmful)return
cache[hash] = { cache[hash] = {
suspect: true, suspect: true,
name: hashToUrl[hash].split("/").pop(), name: hashToUrl[hash].split("/").pop(),
type: hashToUrl[hash].endsWith(".js") ? "Plugin" : "Theme" type: hashToUrl[hash].endsWith(".js") ? "Plugin" : "Theme",
harm: isHarmful
} }
let elements = Array.from(document.querySelectorAll(`a[href="${hashToUrl[hash]}"]`)).filter(e => !e.classList.contains("da-fileNameLink")).map(e => e.parentElement) console.log(`Found potentially dangerous virus: ${cache[hash].name}`)
renderToElements(elements, cache[hash], cache[hash].name)
}*/ renderToElements(id, cache[hash], cache[hash].name)
}
const hashToUrl = {} const hashToUrl = {}
function processAttachment(attachment){ function processAttachment(attachment, id){
if(!attachment.url.startsWith("https://cdn.discordapp.com/"))return if(!attachment.url.startsWith("https://cdn.discordapp.com/"))return document.getElementById(id).remove()
if(!attachment.filename.endsWith(".plugin.js") && !attachment.filename.endsWith(".theme.css"))return if(!attachment.filename.endsWith(".plugin.js") && !attachment.filename.endsWith(".theme.css"))return document.getElementById(id).remove()
let nextHash = (hash, data) => { let nextHash = (hash, data) => {
if(!cache[hash]){ if(!cache[hash]){
nodeFetch("https://raw.githubusercontent.com/Lightcord/filehashes/master/hashes/"+hash, { nodeFetch("https://cdn.jsdelivr.net/gh/Lightcord/filehashes@master/hashes/"+hash, { // Using node-fetch to bypass cors
headers: { headers: {
"User-Agent": electron.remote.getCurrentWebContents().userAgent "User-Agent": electron.remote.getCurrentWebContents().userAgent // have to set user-agent
} }
}).then(async res => { }).then(async res => {
if(res.status !== 200)return //checkViruses(hash, data) if(res.status !== 200)return checkViruses(hash, data, id)
const result = await res.json() const result = await res.json()
debug&&console.log(`Hash valid:`, result)
cache[hash] = result cache[hash] = result
let elements = Array.from(document.querySelectorAll(`a[href="${attachment.url}"]`)).filter(e => !e.classList.contains("da-fileNameLink")).map(e => e.parentElement) renderToElements(id, result, attachment.filename)
renderToElements(elements, result, attachment.filename)
}).catch(()=>{}) }).catch(()=>{})
}else{ }else{
const result = cache[hash] const result = cache[hash]
debug&&console.log(`Hash Cached:`, result)
let elements = Array.from(document.querySelectorAll(`a[href="${attachment.url}"]`)).filter(e => !e.classList.contains("da-fileNameLink")).map(e => e.parentElement) renderToElements(id, result, attachment.filename)
renderToElements(elements, result, attachment.filename)
} }
} }
@ -195,10 +227,8 @@ function processAttachment(attachment){
}) })
res.body.on("end", () => { res.body.on("end", () => {
const hashResult = hash.digest("hex") const hashResult = hash.digest("hex")
debug&&console.log(`Calculated hash for file ${attachment.filename}: ${hashResult}`)
cache2[attachment.url] = hashResult cache2[attachment.url] = hashResult
hashToUrl[hashResult] = attachment.url hashToUrl[hashResult] = attachment.url
nextHash(hashResult, data) nextHash(hashResult, data)
@ -212,34 +242,68 @@ const childModule = BDModules.get(e => e.childContainer)[0]
/** /**
* *
* @param {HTMLDivElement[]} elements * @param {HTMLDivElement[]} elements
* @param {{type: "Theme"|"Plugin", name: string, official?: boolean}|{suspect:true, type: "Theme"|"Plugin", name: string}} result * @param {{type: "Theme"|"Plugin", name: string, official?: boolean}|{suspect:true, type: "Theme"|"Plugin", name: string, harm: string}} result
*/ */
function renderToElements(elements, result, filename){ function renderToElements(id, result, filename){
const div = document.getElementById(id)
if(!div || div.childNodes.length > 0)return // already certified, so don't do it.
// TODO: implements suspect plugins.
elements.forEach(e => {
if(e.childNodes.length > 3)return
const div = document.createElement("div")
e.appendChild(div)/*
if(result.suspect){ if(result.suspect){
e.style.backgroundColor = "#E13838" try{
div.parentNode.style.borderColor = "rgb(240, 71, 71)"
/** /**
* *
* @param {HTMLElement} node * @param {HTMLElement} node
*//* */
let nextNode = (node) => { let nextNode = (node) => {
for(let child of node.children){ for(let child of node.children){
if(child.tagName === "a"){ if(child.tagName === "A"){
child.addEventListener("click", (e) => { child.addEventListener("click", (e) => {
e.preventDefault() e.preventDefault()
alert("You are about to download a suspect "+result.type.toLowerCase()+". Are you sure ? If yes, then please copy and paste the URL directly into your browser.") e.stopImmediatePropagation()
Utils.showConfirmationModal(
"Are you sure you want to download this ?",
"The "+result.type.toLowerCase()+" **"+filename+"** might be dangerous **("+result.harm+")**. \n\n**We don't recommand to download it**. However, you can still do it below.",
{
confirmText: "Download Anyway",
cancelText: "Don't !",
danger: true,
onCancel: () => {},
onConfirm: () => {
electron.remote.shell.openExternal(child.href)
}
}
)
}) })
}else if(["div"].includes(child.tagName)){ }else if(["div"].includes(child.tagName.toLowerCase())){
nextNode(child) nextNode(child)
} }
} }
} }
nextNode(e) nextNode(div.parentNode)
}else */if(!result.official){ }catch(e){
console.error(e)
}
BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" is potentially dangerous."},
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}},
BDV2.react.createElement("svg", {className: BDModules.get(e => e.svg)[0].svg, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 40 32"},
BDV2.react.createElement("rect", {
x:"0",
y:"0",
width:"32",
height:"32",
mask:"url(#svg-mask-avatar-status-round-32)",
fill:"#f04747",
mask:"url(#svg-mask-status-dnd)",
className:BDModules.get(e => e.pointerEvents)[0].pointerEvents
})
)
)
), div)
}else if(!result.official){
div.parentNode.style.borderColor = "#4087ed"
BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" is certified by Lightcord."}, BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" is certified by Lightcord."},
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}}, BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}},
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2"}, BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2"},
@ -253,6 +317,7 @@ function renderToElements(elements, result, filename){
) )
), div) ), div)
}else{ }else{
div.parentNode.style.borderColor = "#4087ed"
BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" was made by the developers of Lightcord.",style:"brand"}, BDV2.reactDom.render(BDV2.react.createElement(tooltipWrap, {text: result.type+" "+result.name+" was made by the developers of Lightcord.",style:"brand"},
BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}}, BDV2.react.createElement("div", {className: flowerStarModule.flowerStarContainer, style: {width: "16px", height: "16px"}},
BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2",stroke:"#36393f",style:{color:"#4087ed"}}, BDV2.react.createElement("svg", {className: flowerStarModule.flowerStar, "aria-hidden":"false",width:"16px",height:"16px",viewBox:"0 0 16 15.2",stroke:"#36393f",style:{color:"#4087ed"}},
@ -266,5 +331,4 @@ function renderToElements(elements, result, filename){
) )
), div) ), div)
} }
})
} }

View File

@ -134,3 +134,6 @@
flex-grow: 1; flex-grow: 1;
margin: 40px auto; margin: 40px auto;
} }
.lc-link-disabled-span:hover {
cursor: pointer;
}