Variable List References (Dynamic Variable Setting)
Credit: Discovered by Geotale
- This exploit relies on 2 things:
- Hidden define blocks (i.e. shadow: true) allow unnatural and impossible block configurations to exist within a scratch project, without them being rendered and crashing the program loading the SB3
FIELDSandINPUTSfields for a block actually get merged when Scratch is looking for attributes, which allows us to trick Scratch into looking for aFIELDSfield inINPUTS, and letting it evaluate the input for its value
- The
setVariableToblock usually takes in a field (dropdown, no reporters allowed) for theVARIABLE, and an inputVALUE(reporters allowed) for the value. However, by hiding the block so it doesn't render and crash, we can put theVARIABLEfield into an input.
JSON Snippets
"T": {
"opcode": "data_setvariableto",
"next": null,
"parent": "aY",
"inputs": {
"VALUE": [
3,
"b]",
[
10,
"0"
]
],
"VARIABLE": [
2,
"b^"
]
},
"fields": {},
"shadow": false,
"topLevel": false
},
"b=": {
"opcode": "data_setvariableto",
"next": null,
"parent": "aX",
"inputs": {},
"fields": {
"VARIABLE": [
"variable references",
"g![_rqnFWsV5HR{GB=39"
],
"VALUE": [
[
{
"name": "a"
},
{
"name": "b"
},
{
"name": "c"
}
]
]
},
"shadow": false,
"topLevel": false
},
Pseudo-code representation
define: hidden-setVar(reference, value){
setVariable(reference, value)
}
define: hidden-setUpVarRefs(){
setVariable("variable references", [ // "variable references" is a list
{
"name": "a"
},
{
"name": "b"
},
{
"name": "c"
}
])
}
// Use case
setUpVarRefs()
setVar(itemGet(1, "variable references"), 103) // set the 1st var ref (a) to 103
say($a)
// --- Output ---
103