Skip to main content
Commonmark migration
Source Link

#6502 Machine Code (C64) - Felix Palmen

6502 Machine Code (C64) - Felix Palmen

The correct answer is

8bitsareenough

The code is rather complicated, involving a lot of self modifying. So instead of fully reverse engineering it, you can just use it to crack itself.

Here's a slightly more helpful disassembly of the code, to help understand what happened. The syntax is for KickAssembler.

*=$c000       // LOAD ADDRESS
jsr $aefd     //checks for a comma
jsr $ad9e     /*Reads in an argument. Stores length of it into
                $61, with the address of the stored arg in $62-3*/
jsr $b6a3     /*Evaluates the string, leaving the pointer on $22-3
                and the length on A*/ //I think

ldy #$00
loop: lda thedata,y   
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y      //XOR's A with the y-eth letter of our input
jmp $ffd2               //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048      //drops A in mystery+4, over the constant
lda $c026,y
sta $c045               //overwrites the low byte of mystery
lda $c027,y
sta $c046               //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x              
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018                
rts

Labelling it up like this was enough for me to see that the code XORs a bunch of constants that are hidden around in order to print out what we need. Since XOR is reversible, if you input the desired output, it'll tell you what the key is.

So I switched the last line

/*from sta $d018 
to*/ jsr $ffd2

so it would print the last required input instead of crashing on a wrong input.

And that's that!

If there's any interest, I'll crack the code more.

#6502 Machine Code (C64) - Felix Palmen

The correct answer is

8bitsareenough

The code is rather complicated, involving a lot of self modifying. So instead of fully reverse engineering it, you can just use it to crack itself.

Here's a slightly more helpful disassembly of the code, to help understand what happened. The syntax is for KickAssembler.

*=$c000       // LOAD ADDRESS
jsr $aefd     //checks for a comma
jsr $ad9e     /*Reads in an argument. Stores length of it into
                $61, with the address of the stored arg in $62-3*/
jsr $b6a3     /*Evaluates the string, leaving the pointer on $22-3
                and the length on A*/ //I think

ldy #$00
loop: lda thedata,y   
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y      //XOR's A with the y-eth letter of our input
jmp $ffd2               //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048      //drops A in mystery+4, over the constant
lda $c026,y
sta $c045               //overwrites the low byte of mystery
lda $c027,y
sta $c046               //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x              
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018                
rts

Labelling it up like this was enough for me to see that the code XORs a bunch of constants that are hidden around in order to print out what we need. Since XOR is reversible, if you input the desired output, it'll tell you what the key is.

So I switched the last line

/*from sta $d018 
to*/ jsr $ffd2

so it would print the last required input instead of crashing on a wrong input.

And that's that!

If there's any interest, I'll crack the code more.

6502 Machine Code (C64) - Felix Palmen

The correct answer is

8bitsareenough

The code is rather complicated, involving a lot of self modifying. So instead of fully reverse engineering it, you can just use it to crack itself.

Here's a slightly more helpful disassembly of the code, to help understand what happened. The syntax is for KickAssembler.

*=$c000       // LOAD ADDRESS
jsr $aefd     //checks for a comma
jsr $ad9e     /*Reads in an argument. Stores length of it into
                $61, with the address of the stored arg in $62-3*/
jsr $b6a3     /*Evaluates the string, leaving the pointer on $22-3
                and the length on A*/ //I think

ldy #$00
loop: lda thedata,y   
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y      //XOR's A with the y-eth letter of our input
jmp $ffd2               //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048      //drops A in mystery+4, over the constant
lda $c026,y
sta $c045               //overwrites the low byte of mystery
lda $c027,y
sta $c046               //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x              
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018                
rts

Labelling it up like this was enough for me to see that the code XORs a bunch of constants that are hidden around in order to print out what we need. Since XOR is reversible, if you input the desired output, it'll tell you what the key is.

So I switched the last line

/*from sta $d018 
to*/ jsr $ffd2

so it would print the last required input instead of crashing on a wrong input.

And that's that!

If there's any interest, I'll crack the code more.

edited body
Source Link
A Gold Man
  • 280
  • 2
  • 9

#6502 Machine Code (C64) - Felix Palmen

The correct answer is

8bitsareenough

The code is rather complicated, involving a lot of self modifying. So instead of fully reverse engineering it, you can just use it to crack itself.

Here's a slightly more helpful disassembly of the code, to help understand what happened. The syntax is for KickAssembler.

*=$c000       // LOAD ADDRESS
jsr $aefd     //checks for a comma
jsr $ad9e     /*Reads in an argument. Stores length of it into
                $61, with the address of the stored arg in $62-3*/
jsr $b6a3     /*Evaluates the string, leaving the pointer on $22-3
                and the length on A*/ //I think

ldy #$00
loop: lda thedata,y   
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y      //XOR's A with the y-eth letter of our input
jmp $ffd2               //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048      //drops A in mystery+1mystery+4, over the constant
lda $c026,y
sta $c045               //overwrites the low byte of mystery
lda $c027,y
sta $c046               //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x              
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018                
rts

Labelling it up like this was enough for me to see that the code XORs a bunch of constants that are hidden around in order to print out what we need. Since XOR is reversible, if you input the desired output, it'll tell you what the key is.

So I switched the last line

/*from sta $d018 
to*/ jsr $ffd2

so it would print the last required input instead of crashing on a wrong input.

And that's that!

If there's any interest, I'll crack the code more.

#6502 Machine Code (C64) - Felix Palmen

The correct answer is

8bitsareenough

The code is rather complicated, involving a lot of self modifying. So instead of fully reverse engineering it, you can just use it to crack itself.

Here's a slightly more helpful disassembly of the code, to help understand what happened. The syntax is for KickAssembler.

*=$c000       // LOAD ADDRESS
jsr $aefd     //checks for a comma
jsr $ad9e     /*Reads in an argument. Stores length of it into
                $61, with the address of the stored arg in $62-3*/
jsr $b6a3     /*Evaluates the string, leaving the pointer on $22-3
                and the length on A*/ //I think

ldy #$00
loop: lda thedata,y   
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y      //XOR's A with the y-eth letter of our input
jmp $ffd2               //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048      //drops A in mystery+1, over the constant
lda $c026,y
sta $c045               //overwrites the low byte of mystery
lda $c027,y
sta $c046               //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x              
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018                
rts

Labelling it up like this was enough for me to see that the code XORs a bunch of constants that are hidden around in order to print out what we need. Since XOR is reversible, if you input the desired output, it'll tell you what the key is.

So I switched the last line

/*from sta $d018 
to*/ jsr $ffd2

so it would print the last required input instead of crashing on a wrong input.

And that's that!

If there's any interest, I'll crack the code more.

#6502 Machine Code (C64) - Felix Palmen

The correct answer is

8bitsareenough

The code is rather complicated, involving a lot of self modifying. So instead of fully reverse engineering it, you can just use it to crack itself.

Here's a slightly more helpful disassembly of the code, to help understand what happened. The syntax is for KickAssembler.

*=$c000       // LOAD ADDRESS
jsr $aefd     //checks for a comma
jsr $ad9e     /*Reads in an argument. Stores length of it into
                $61, with the address of the stored arg in $62-3*/
jsr $b6a3     /*Evaluates the string, leaving the pointer on $22-3
                and the length on A*/ //I think

ldy #$00
loop: lda thedata,y   
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y      //XOR's A with the y-eth letter of our input
jmp $ffd2               //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048      //drops A in mystery+4, over the constant
lda $c026,y
sta $c045               //overwrites the low byte of mystery
lda $c027,y
sta $c046               //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x              
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018                
rts

Labelling it up like this was enough for me to see that the code XORs a bunch of constants that are hidden around in order to print out what we need. Since XOR is reversible, if you input the desired output, it'll tell you what the key is.

So I switched the last line

/*from sta $d018 
to*/ jsr $ffd2

so it would print the last required input instead of crashing on a wrong input.

And that's that!

If there's any interest, I'll crack the code more.

Source Link
A Gold Man
  • 280
  • 2
  • 9

#6502 Machine Code (C64) - Felix Palmen

The correct answer is

8bitsareenough

The code is rather complicated, involving a lot of self modifying. So instead of fully reverse engineering it, you can just use it to crack itself.

Here's a slightly more helpful disassembly of the code, to help understand what happened. The syntax is for KickAssembler.

*=$c000       // LOAD ADDRESS
jsr $aefd     //checks for a comma
jsr $ad9e     /*Reads in an argument. Stores length of it into
                $61, with the address of the stored arg in $62-3*/
jsr $b6a3     /*Evaluates the string, leaving the pointer on $22-3
                and the length on A*/ //I think

ldy #$00
loop: lda thedata,y   
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y      //XOR's A with the y-eth letter of our input
jmp $ffd2               //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048      //drops A in mystery+1, over the constant
lda $c026,y
sta $c045               //overwrites the low byte of mystery
lda $c027,y
sta $c046               //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x              
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018                
rts

Labelling it up like this was enough for me to see that the code XORs a bunch of constants that are hidden around in order to print out what we need. Since XOR is reversible, if you input the desired output, it'll tell you what the key is.

So I switched the last line

/*from sta $d018 
to*/ jsr $ffd2

so it would print the last required input instead of crashing on a wrong input.

And that's that!

If there's any interest, I'll crack the code more.