PNG Number (100 pts)
Solved by: sardinachanx, zookham
Problem:
Calculate the sum of decimal digits of the number represented in big-endian by the raw pixel data of number.png in BGR byte order.
Files:
Hint:
Patience.
Solution:
Very typical algo problem! The question looks relatively straight-forward - after looking up the exact definition of big endian I coded up a solution, with one caveat. Using the Java inbuilt arbitrary precision integer library (BigInteger), the solution ran for 6 hours. Towards the end of the competition (when they fixed the flag), I didn't have much time left and our current answers were somehow wrong, so I ended up using another AP integer library (APInt) to code up the solution. That reduced the runtime of the entire solution to under 3 minutes. I also split the solution up into two parts so I could resume my progress at a particular point.
Code:
Reading in the raw RGB data from the png
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.imageio.ImageIO;
public class JPEGNumber {
public static void main(String[]args){
BufferedWriter bw = null;
try {
BufferedImage image = ImageIO.read(new File("number.png"));
int width = image.getWidth();
int height = image.getHeight();
int[] all = image.getRGB(0, 0, width, height, null, 0, image.getWidth());
System.out.println("I'm done with reading!");
StringBuilder sb = new StringBuilder();
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
int current = all[y * width + x];
int colorRed = (current >> 16) & 0xFF;
int colorGreen = (current >> 8) & 0xFF;
int colorBlue = (current) & 0xFF;
sb.append(pad(Integer.toHexString(colorBlue)));
sb.append(pad(Integer.toHexString(colorGreen)));
sb.append(pad(Integer.toHexString(colorRed)));
}
}
File output = new File("hex.txt");
try{
bw = new BufferedWriter(new FileWriter(output));
bw.write(sb.toString());
}
catch(IOException e){
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(bw != null){
try{
bw.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
public static String pad(String s){
if(s.length() == 0){
return "00";
}
else if(s.length() == 1){
return "0" + s;
}
else{
return s;
}
}
}
Converting the output hex from above to a decimal number and finding the digital root
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import org.apfloat.Apint;
public class PNGRead {
public static void main(String[]args){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new FileReader(new File("hex.txt")));
String s = br.readLine();
Apint bi = new Apint(s, 16);
System.out.println("int created");
try{
bw = new BufferedWriter(new FileWriter(new File("dec.txt")));
String dec = bi.toRadix(10).toString(true);
bw.write(dec);
System.out.println("done");
long count = 0;
long length = dec.length();
for(int i = 0; i < length; i++){
if(i > length - 2){
System.out.println(dec.substring(i, i + 1));
}
count += Integer.parseInt(dec.substring(i, i + 1));
}
System.out.println(count);
}
catch(IOException e){
e.printStackTrace();
}
}
catch(IOException e){
e.printStackTrace();
}
finally{
if(br != null){
try{
br.close();
} catch(IOException e){
e.printStackTrace();
}
}
if(bw != null){
try{
bw.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
}
}
FLAG: sctf{102261653}