onehourhacks-GameSpot
Saturday, September 7, 2013
Wednesday, June 26, 2013
Simple Credit Card Validator
Validating credit cards numbers is a fairly simple job, and there are no short supply of algorithms out there you can easily download to do it. That being said, it is a perfect algorithm to write in Haxe for the following reasons:
(Note that the ISBN10 algorithm holds some of these same properties.)
- Speed isn't super critical
- It doesn't involve the system in any way
- You can use the same code across PHP, JS, Java, C++, C#, Actionscript etc.
- The same code would be useful in all contexts.
Algorithm
The algorithm realized here is the Luhn algorithm. You can do the formal proofs with some discrete math, or trust the Wikipedia Article that it is useful because:- It detects any one digit error e.g. 1235 instead of 1234
- It detects any one transposition e.g. 1324 instead of 1234
(Note that the ISBN10 algorithm holds some of these same properties.)
The Code
/**
A simple credit card validator that just runs the luhn algorithm against the
given number. It doesn't even check to see if the string is long enough!
**/
class Validator
{
/**
Call this function with a string of digits that represent a credit card
number.
**/
public static function validate(cardNumber : String) : Bool
{
return (luhn(cardNumber) == 0);
}
private static function luhn(numericString : String) : Int
{
var output = stringToDigitArray(numericString);
var sum : Int = 0;
var isEven : Bool = true;
for( i in output.iterator())
{
if(isEven)
{
sum += sumOfDigits(i * 2);
}
else
{
sum += i;
}
isEven = !isEven; // Invert sign for next iteration
}
return sum % 10;
}
private static function stringToDigitArray(numericString : String) : Array<Int>
{
var output = new Array<Int>();
for( i in 0...numericString.length)
{
output.push(Std.parseInt(numericString.charAt(i)));
}
return output;
}
private static function sumOfDigits(number : Int) : Int
{
var sum : Int = 0;
while(number != 0)
{
sum += number % Std.int(10);
number = Std.int(number / Std.int(10));
}
sum += number;
return sum;
}
/* Examples */
public static function main() : Void
{
// False
trace(Validator.validate("1111111111111111"));
// All true below this point
trace(Validator.validate("4271058012370682"));
trace(Validator.validate("4052047247466840"));
trace(Validator.validate("4250112315345738"));
trace(Validator.validate("4302220036446780"));
trace(Validator.validate("4271382676044056"));
trace(Validator.validate("4027883785016825"));
trace(Validator.validate("4125875428334483"));
trace(Validator.validate("4231380166327600"));
trace(Validator.validate("4820020713741757"));
trace(Validator.validate("4013112216053363"));
}
}
Friday, June 21, 2013
HOWTO Find and Restore a Deleted SVN File/Folder
- Change directories to your SVN project.
- Run
svn log -v > all_history.txt
- Open
all_history.txt
and find the file you want (Ctrl + F is your friend!) - Make sure the line of the file you want begins with a D, this means it was deleted.
- Look up above that file for the revision number, subtract one from it.
- Run a new checkout for the version right beforehand i.e.:
svn co http://hostname/path/to/files_parent_directory@revision#_right_before
Example
We want to find DataFeedList.java
, here is the svn log:
------------------------------------------------------------------------
r24843 | joslewis | 2013-04-14 10:24:28 -0600 (Sun, 14 Apr 2013) | 1 line
Changed paths:
D /trunk/software/src/bmod/gui/widgets/DataFeedList.java
D /trunk/software/src/bmod/gui/widgets/FilterableComponentList.java
D /trunk/software/src/bmod/gui/widgets/JValidatingTextField.java
D /trunk/software/src/bmod/gui/widgets/WebButton.java
D /trunk/software/src/bmod/gui/widgets/WebMenuItem.java
M /trunk/software/src/bmod/plugin/generic/gui/ReportBugMenuItem.java
Modified ReportBugMenuItem to now work without WebButton. -~400 lines.
------------------------------------------------------------------------
We can see it was deleted (D) during revision r24843
by me on 2013-04-14 10:24:28 -0600. That means we want to actually get the version right before it was deleted, so we'll check out version 24842.
It was in the folder: /trunk/software/src/bmod/gui/widgets/
, so we'll craft a new checkout with the information to get it back:
svn co http://svn.host.com/trunk/software/src/bmod/gui/widgets@24842
Run this in another folder so you don't overwrite the existing source, and you'll find the deleted item in it!
Friday, June 7, 2013
The Haxe Programming Language
This is a language that has seemed to slip by under the radar for the most part.
It has a reasonable standard library that feels designed, much like Python's. The syntax is Go like, with identifiers following names:
Compilation is straightforward, consisting of an internal build system that resolves libraries well, and a global repository that you can pull new packages from.
One of the biggest benefits of this language is its ability to compile and run on so many platforms; it easily handles:
Haxe
, commonly pronounced "hex" or "hacks" is a language that targets many virtual machines, instead of the more common virtual machine that targets many languages.It has a reasonable standard library that feels designed, much like Python's. The syntax is Go like, with identifiers following names:
class WebFetch
{
static function main()
{
var output = haxe.Http.requestUrl("http://www.google.com/");
Sys.print(output);
}
}
When built, this program is a ~68Kb JAR file when targeting Java or a 550Kb ELF when generating C++.Compilation is straightforward, consisting of an internal build system that resolves libraries well, and a global repository that you can pull new packages from.
One of the biggest benefits of this language is its ability to compile and run on so many platforms; it easily handles:
- Android
- Flash
- Linux
- Mac
- Windows
- HTML + JS
- PHP
- Java (in Beta)
Example Uses
- You're a web-developer and have some business code that needs to target language of the day. Haxe can compile to language of the day without the need to translate.
- You want to code a cross-platform game to reach as broad of an audience as possible without re-writing lots of code.
- You want to develop a client for an API you publish so developers will actually use it without learning all of the languages it is going to be used in or maintaining the libraries.
- You want to develop an app that is future proof, but don't mind it being a little ugly.
Pitfalls
- There is no standardized UI system.
- The coding conventions are a strange to begin with.
- There are some obvious deficiencies in the standard library (no string compare)
- Code is slightly larger than it would be natively.
Conclusion
Overall, Haxe is a good language that I see myself using in the long run because it is so future-proof and well designed. Plus, the ability to do things easily cannot be underestimated. The example above would have taken over 100 lines of Java and about the same in C++, instead it took eight and thirty seconds to put together after knowing the language less than twenty-four hours.Thursday, May 30, 2013
Finding Strings in Raw Data
Occasionally, you'll find yourself wishing you could pull out human-readable strings from binary formats, like
The method I found that works relatively well is this:
JPEGs
, EXEs
or even raw disk dumps. This may be for a variety of reasons, such as:- Performing malware analysis
- Finding lost files
- Efficient searching
Algorithm
Actually extracting interesting text from a file is somewhat difficult because,- you don't know what format the file is in
- you don't know what language the text is in
- you don't know how relevant a snippet is
The method I found that works relatively well is this:
- Look for runs of printable characters in a file with length greater than 5
- Look for runs of uppercase letters, lowercase letters, or numbers.
- For each character of each run, set the value of the nth letter to n.
- Sum the run totals
- Sort the scores and return.
Outputs
The software below strips special terminal characters (like newlines and carriage returns), and prints out items in the following format:<score><tab><file><tab><string><newline>
Example:00000250 dd.img &'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
00000176 dd.img .IEC 61966-2.1 Default RGB colour space - sRGB
00000176 dd.img .IEC 61966-2.1 Default RGB colour space - sRGB
00000138 dd.img ;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 95
00000136 dd.img ,Reference Viewing Condition in IEC61966-2.1
00000136 dd.img ,Reference Viewing Condition in IEC61966-2.1
00000099 dd.img Copyright (c) 1998 Hewlett-Packard Company
00000078 dd.img <?xpacket begin='
00000075 dd.img Hhttp://ns.adobe.com/xap/1.0/
00000075 dd.img Adobe Photoshop CS2 Macintosh
00000063 dd.img $54545,,4,44455,554,,4,,,4,55456,,,,,,/5554-,,4,24,
00000058 dd.img IEC http://www.iec.ch
00000058 dd.img IEC http://www.iec.ch
00000051 dd.img bottomOutsetlong
00000046 dd.img rightOutsetlong
It appears this unallocated space actually has files!Operation
Save the below code toreader.py
and provide it paths to the files you want it to read. There are no parameters.Source
#!/usr/bin/env python
'''
A program that extracts strings from binary files.
Usage: reader.py file [file ...]
Copyright (c) 2013, Joseph Lewis III <joseph@josephlewis.net> | <joehms22@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
import sys
ALPHABET_UPPER = frozenset("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
ALPHABET = frozenset("abcdefghijklmnopqrstuvwxyz,-. \t\n")
NUMBERS = frozenset("0123456789")
OTHER_CHARACTERS = frozenset("!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r")
PRINTABLE = frozenset('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r')
READ_BLOCK_SIZE_B = 2048
def type_of_char(c):
if c in ALPHABET_UPPER:
return 'A'
if c in ALPHABET:
return 'a'
if c in NUMBERS:
return 'n'
return 'o'
def value_of_string(string):
''' A heuristic to give an approximate value to a string. '''
# make sure the string isn't total junk
if all([c in OTHER_CHARACTERS for c in string]):
return 0
types = [type_of_char(c) for c in string]
runs = [0 for c in string]
# higher runs are better
for i in range(1, len(types)):
if types[i] == 'o':
runs[i] = 0
elif types[i] == types[i - 1]:
runs[i] = runs[i - 1] + 1
else:
runs[i] = 0
return sum(runs)
def process_string(string, extracts):
if len(string) < 5:
return
score = value_of_string(string)
if score > 0:
extracts.append((score, path, string))
def extract_strings(path, extracts):
'''Extracts "interesting" strings from a file'''
mystr = []
with open(path, 'rb') as fd:
chars = fd.read(READ_BLOCK_SIZE_B)
while chars != "":
for char in chars:
if char in "\r\n":
mystr.append(" ")
elif char in PRINTABLE:
mystr.append(char)
elif len(mystr) == 0:
continue
else:
process_string("".join(mystr), extracts)
mystr = []
chars = fd.read(READ_BLOCK_SIZE_B)
process_string("".join(mystr), extracts)
if __name__ == "__main__":
if len(sys.argv) == 1:
print("Usage: {} file [file ...]".format(sys.argv[0]))
exit(1)
# a list of tuples (score, document, string)
extracts = []
for path in sys.argv[1:]:
extract_strings(path, extracts)
extracts = sorted(extracts, reverse=True)
for score, path, string in extracts:
print("{:08.0f}\t{}\t{}".format(score, path, string))
Friday, May 24, 2013
Friday Operating System News
Operating Systems
NixOS is a neat little OS that is built around a single config file. The file can be moved to a different computer, and it'll set itself up as a clone, or as you're more likely to use it, as a single file that does version control on your system (so next time you upgrade, you can roll it back right away!)Jolla has released it's first phones running Sailfish OS.
Wednesday, May 15, 2013
Finding Deleted JPEGs in Disk Dumps
If you've ever accidentally deleted items from your digital camera, or want to find them from a drive that has been lost, this script could be for you!
It works by looking through a disk image for a sequence of bytes that signify the beginning and end of a JPEG image.
Then compile it:
It works by looking through a disk image for a sequence of bytes that signify the beginning and end of a JPEG image.
Running It
First save the below script as ImageCarver.javaThen compile it:
javac ImageCarver.java
Afterwards, run it with the path to the disk image you want it to search:java ImageCarver disk.img
It will report images it found, as well as the locations in the disk that it found them:1.jpg 0xe3fa 0x10272
2.jpg 0xe000 0x20865
3.jpg 0x1000 0x2557e
4.jpg 0x41000 0x4437d
5.jpg 0x26000 0x654d4
6.jpg 0x25000 0x96816
7.jpg 0x86000 0x9eca0
8.jpg 0x6d000 0xdc614
9.jpg 0xe2000 0xe7ac9
10.jpg 0xa4000 0xeb28a
11.jpg 0xed000 0xfc9a9
12.jpg 0x136000 0x13b08e
13.jpg 0x1b5144 0x1b629e
14.jpg 0x1b5000 0x1b794a
15.jpg 0x1b67f0 0x1bea75
16.jpg 0x1c9000 0x1cfada
17.jpg 0x22d000 0x237824
18.jpg 0x281000 0x288928
The Script
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.LinkedList;
/**
* Carves images from a file given from the command line.
*
* @author Joseph Lewis <joehms22@gmail.com>
*
*/
public class ImageCarver
{
byte[] STARTING_BYTES = new byte[]{(byte)0xFF, (byte)0xD8,(byte)0xFF};
byte[] ENDING_BYTES = new byte[]{(byte)0xFF,(byte)0xD9};
int imgno = 0;
/**
* Carves images out of a file.
* @param sbc - the byte channel to read from.
* @throws IOException - on a file error
*/
public ImageCarver(SeekableByteChannel sbc) throws IOException
{
// find all potential starting and ending points in the file.
LinkedList<Long> startingPoints = ringMatch(sbc, STARTING_BYTES);
LinkedList<Long> endingPoints = ringMatch(sbc, ENDING_BYTES);
// keep writing out we're out of images
while(startingPoints.size() > 0)
{
carveImage(sbc, startingPoints, endingPoints);
}
}
/**
* Carves an image out of the file.
* @param sbc - the channel to read from
* @param starts - the start positions of the image
* @param ends - the end positions of the image
* @throws IOException - on error
*/
public void carveImage(SeekableByteChannel sbc, LinkedList<Long> starts, LinkedList<Long> ends) throws IOException
{
// clear off no longer useful end points
while(starts.peek() > ends.peek())
{
ends.pop();
}
// If ends is empty, add the literal file end.
if(ends.size() == 0)
{
ends.push(sbc.size());
}
// get our starting position.
long sp = starts.pop();
// Check to see if there's an image inside of us.
if(starts.size() > 0 && starts.peek() < ends.peek())
{
carveImage(sbc, starts, ends);
}
// get our closest end point.
long endloc = ends.pop();
imgno++;
createImage(imgno + ".jpg", sbc, sp, endloc);
}
/**
* Extracts an image from the SeekableByteChannel.
* @param name - the image name
* @param src - the channel to read from
* @param begin - the offset to the beginning of the image
* @param end - the offset to the end of the image
* @throws IOException - on error
*/
public void createImage(String name, SeekableByteChannel src, long begin, long end) throws IOException
{
// alert the user about the image we're outputting
System.out.println(String.format("%s 0x%x 0x%x", name, begin, end));
// write out the given slice of bytes
try(OutputStream os = Files.newOutputStream(Paths.get(name), StandardOpenOption.CREATE))
{
src.position(begin);
ByteBuffer b = ByteBuffer.allocate((int) (end - begin));
src.read(b);
os.write(b.array());
}
}
/**
* Searches through a channel looking for a given array of bytes to match.
*
* @param sbc - the channel to read from
* @param toMatch - the bytes to match in the stream
* @return a list of all offsets where the given bytes are found
* @throws IOException - on file read error
*/
public LinkedList<Long> ringMatch(SeekableByteChannel sbc, byte[] toMatch) throws IOException
{
// holds all found vars
LinkedList<Long> finds = new LinkedList<Long>();
for(long i = 0; i < sbc.size() - toMatch.length; i++)
{
ByteBuffer b = ByteBuffer.allocate(toMatch.length);
sbc.position(i);
sbc.read(b);
boolean matches = true;
for(int j = 0; j < toMatch.length; j++)
{
if(b.array()[j] != toMatch[j])
{
matches = false;
break;
}
}
if(matches)
{
finds.add(i);
}
}
return finds;
}
public static void main(String[] args) throws Exception
{
// Make sure we have an arg.
if(args.length != 1)
{
System.out.println("Must supply exactly one argument.");
return;
}
Path p = Paths.get(args[0]);
try (SeekableByteChannel sbc = Files.newByteChannel(p))
{
new ImageCarver(sbc);
}
catch (IOException x)
{
System.out.println("Caught exception: " + x);
}
}
}
Subscribe to:
Posts (Atom)