Random BnS Crap (Sniffed from Client)

04/01/2016 21:00 killzone#1
Looking for a way to access the Market outside the client, no avail.
Here's what I sniffed so far.
Code:
GET /res/js/bns.market.jquery.js?v=1410281030 HTTP/1.1
Host: na-bnsmarket.ncsoft.com
Connection: keep-alive
User-Agent: BnsIngameBrowser
Referer: http://na-bnsmarket.ncsoft.com/bns/bidder/home.web?npc=false
Accept: */*
Accept-Encoding: gzip,deflate
Accept-Charset: ,utf-8;q=0.7,*;q=0.3
Cookie: commonWebPath=/web; localWebPath=/english/web; language=en; GPVLU=396cb904b7aa4f4cd79fcd5f727b3b2833bfc135d4fb4eeb741df60c16ee476219dc69b22950af6120a0fb0534b3638befb6cc03b9fe8e084a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d24a1a222355efd1d2774b7791592d95892fe5dd5ccb15b09ea5892ab2dbba128555531a450067046d68c131fcc14fd05067717f40c4648b5850da5d87cd8c12177da728c62b5fcb7a02eeb599aad063e173971bd3eee5b950; SessionIndex=1; presence=2; pc=lvExAAAAAAA=; world=109; pcName=Flora%20Valentine; pcLevel=20; pcMasteryLevel=0; pcRace=LYN; pcJob=SU; pcFaction=1; pcFaction2=0; pcSex=FEMALE; pcMoney=138435; uiColorIndex=23; uiColorRed=110; uiColorGreen=110; uiColorBlue=110; uiColorAlpha=128; GPGAMEBNSMARKETFROMNPC=false; JSESSIONID=9E869186A0CD4117DAFA8EB5019A1258.ncw-bladensoule-web-01


HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Last-Modified: Fri, 11 Dec 2015 17:33:52 GMT
Content-Type: application/javascript;charset=UTF-8
Content-Length: 9776
Date: Fri, 01 Apr 2016 18:53:41 GMT
Connection: close

var BNS = (function (B, $) {
	var callback = {};
	function isSuccess (status) {
		var code = ($.type(status) !== "string") ? String(status) : status;
		return code === "1" ? true : false;
	}
	// register callback function
	B.registerCallback = function (name, func) {
		callback[name] = func;
	};
	// callback for RegisterBid
	B.attendAuction = function (sale, status, price) {
		if (isSuccess(status)) callback["attendAuction"](sale, price);
	};
	// callback for UpdateBid
	B.rebid = function (sale, bid, status, inc) {
		if (isSuccess(status)) callback["rebid"](sale, bid, inc);
	};
	// callback for RegisterPurchase
	B.purchase = function (sale, status) {
		if (isSuccess(status)) callback["purchase"](sale);
	};
	// callback for drag and drop or right click on item
	B.setItem = function (item, level, pos, amount, max) {
		callback["setItem"](item, pos, amount, max);
	};
	// callback for rgith click on waiting for sale item
	B.clearItemToSell = function () {
		callback["clearItemToSell"]();
	};
	//callback for RegisterSale
	B.register = function () {
		callback["register"]();
	};
	// callback for AbandonBid
	B.abandonBid = function (sale, status) {
		if (isSuccess(status)) callback["abandonBid"](sale);
	};
	// callback for ctrl + left click on item
	B.setItemName = function (itemName) {
		callback["setItemName"](itemName);
	};
	// callback for cancel sale
	B.cancelSaleResult = function (saleId, result) {
		callback["cancelSaleResult"](saleId, result);
	}
	return B;
}(BNS || {}, jQuery));

BNS.Command = (function () {
	var commands = {
		HOME:"nc://bns.Market/Home",
		SEARCH:"nc://bns.Market/Search",
		REGISTER_BID:"nc://bns.Market/RegisterBid",
		UPDATE_BID:"nc://bns.Market/UpdateBid",
		REGISTER_PURCHASE:"nc://bns.Market/RegisterPurchase",
		SELL:"nc://bns.Market/Sell",
		REGISTER_SALE:"nc://bns.Market/RegisterSale",
		MY_BIDS:"nc://bns.Market/MyBids",
		ABANDON_BID:"nc://bns.Market/AbandonBid",
		ITEM_TOOLTIP:"nc://bns.Market/ItemTooltip",
		INVEN_ITEM_TOOLTIP:"nc://bns.Market/InventoryItemTooltip",
		OPEN_CONTEXT_MENU:"nc://bns.Market/OpenContextMenu",
		CLEAR_ITEM_TO_SELL:"nc://bns.Market/ClearItemToSell",
		SET_EDITBOX_VALUE:"nc://bns.Market/SetEditBoxValue",
		CANCEL_SALE:"nc://bns.Market/CancelSale",
		
		CHART_LOWPRICE:"/bns/chart/lowprice.web",
		CHART_OHLC:"/bns/chart/ohlc.web",
		
		// item preview and hyper text
		ITEM_PREVIEW:"nc://bns.Common/ItemPreview",
		ITEM_HYPERTEXT:"nc://bns.Common/ItemHyperText",
		
		//available http reuqest (2012/07/17)
		WEB_SELL:"/bns/seller/home.web",
		
		SELL_ITEM_INFO:"/bns/seller/item.web",
		SELL_ITEM_PRICE:"/bns/seller/itemprice.web",
		BIDDERS_INFO:"/bns/bidder/bidders.web",
		PURCHASE_LOG:"/bns/bidder/purchaselog.web",
		
		FAVORITE:"/bns/favorite/items.web",
		ADD_FAVORITE:"/bns/favorite/insert.web",
		DELETE_FAVORITE:"/bns/favorite/delete.web",
		COMMON_ITEM_TOOLTIP:"nc://bns.Common/ItemTooltip"
	};
	
	//commands.MY_BIDS = "/bns/bidder/attends.web";
	//commands.SEARCH = "/bns/bidder/search.web";
	//commands.SELL = "/bns/seller/home.web";

	return commands;
}());

BNS.Constants = (function () {
	var constants = {
		MAX_MONEY:"15000000000"
	};
	return constants;
}());

BNS.Util = (function (CMD, $) {
	function isPossibleJob(itemJob1, itemJob2, characterJob) {
		if (itemJob1 == "NONE" && itemJob2 == "NONE") return true;
		if (itemJob1 == "" && itemJob2 == "") return true;
		if (itemJob1 == characterJob || itemJob2 == characterJob) return true;
		return false;
	}
	var Util = {};
	// make title attribute in element using data json object (data.item, data.amount, data.price, data.topPrice, data.type)
	Util.itemToolTip = function (element, data) {
		var obj = (element instanceof jQuery) ? element : $(element);
		var title;
		if (data.topPrice) {
			title = CMD.ITEM_TOOLTIP+"?itemId="+data.item+"&itemLevel=1"+"&amount="+data.amount+"&price="+data.price+"&topprice="+data.topPrice+"&type="+data.type;
		} else {
			title = CMD.ITEM_TOOLTIP+"?itemId="+data.item+"&itemLevel=1"+"&amount="+data.amount+"&price="+data.price+"&topprice="+data.price+"&type="+data.type;
		}
		obj.attr("title", title);
		
		obj.on("click", function(event) {
			if (event.shiftKey) location.href=CMD.ITEM_PREVIEW+"?itemId="+data.item + "&itemLevel=1";
			else if (event.ctrlKey) location.href=CMD.ITEM_HYPERTEXT+"?itemId="+data.item + "&itemLevel=1";
		});
	};
	Util.commonItemToolTip = function (element, itemId) {
		var obj = (element instanceof jQuery) ? element : $(element);
		var title = CMD.COMMON_ITEM_TOOLTIP + "?itemId=" + itemId + "&itemLevel=1";
		obj.attr("title", title);
	};
	// add icon (seal item, level, job, race, sex)
	//seal item -> lock item -> level item
	Util.itemlIcon = function (element, data, character) {
		Util.itemSeallIcon(element, data, character);
		if ((character.job != "" && character.race != "") && (data.job != "" && character.race != ""))	Util.itemLockIcon(element, data, character);
		if (character.level > 0 && data.level > 0)	Util.itemLevelIcon(element, data, character);
	};
	Util.itemSeallIcon = function (element, data, character) {
		var obj = (element instanceof jQuery) ? element : $(element);
		if ((data.name).indexOf(Messages.get("market.js.common.text.seal")) > -1) {
		//if ((data.name).indexOf(".........") > -1) {
			obj.attr("class", "iconLock Seal ItemLink");
			obj.html(Messages.get("market.js.common.text.unseal"));
			//obj.html("............");
		}
	};
	Util.itemLevelIcon = function (element, data, character) {
		var obj = (element instanceof jQuery) ? element : $(element);
		if (obj.attr("class") == "") {
			if (parseInt(data.level, 10) > parseInt(character.level, 10)) {
				obj.attr("class", "iconLock Level ItemLink");
				obj.html(Messages.get("market.js.common.text.level"));
				//obj.html("............");
			}
		}
	};
	Util.itemLockIcon = function (element, data, character) {
		var obj = (element instanceof jQuery) ? element : $(element);
		if (obj.attr("class") == "") { //job, race, sex
			if ( isPossibleJob(data.job1, data.job2, character.job) == false
					|| (data.race == "NONE" || data.race == "" || data.race == "CAT" || (data.race == character.race)) == false
					|| (data.sex == "NONE" || data.sex == "" || data.sex == character.sex || (data.sex == "FEMALE" && character.sex == "FAMALE"))  == false ) {
				obj.attr("class", "iconLock Job ItemLink");
				obj.html(Messages.get("market.js.common.text.lock"));
				//obj.html("............");
			}
		}
	};
	// make title attribute in element using pos
	Util.inventoryItemToolTip = function (element, pos, max) {
		var obj = (element instanceof jQuery) ? element : $(element);
		var title = CMD.INVEN_ITEM_TOOLTIP+"?pos="+pos+"&amount="+max;
		obj.attr("title", title);
	};
	// make money (number type)
	Util.money = function (gold, silver, bronze) {
		var gp = parseInt(gold, 10);
		var sp = parseInt(silver, 10);
		var bp = parseInt(bronze, 10);
		return (isNaN(gp) === true ? 0 : gp)*10000 + (isNaN(sp) === true ? 0 : sp)*100 + (isNaN(bp) === true ? 0 : bp);
	};
	Util.money.string = function (price) {
		return "<money>"+price+"</money>";
	};
	Util.money.object = function (price) {
		var gold = parseInt(price / 10000 , 10);
		var silver = parseInt((price % 10000) / 100 , 10);
		var bronze = price % 100;
		return {"gold":gold,"silver":silver,"bronze":bronze};
	};
	Util.money.html = function  (price) {
		var money = Util.money.object(price);
		var html = "";
		if (money.gold > 0) html += "<span class='gold'>" + parseInt(money.gold, 10) + " <span>" + Messages.get("market.js.common.text.price_gold") + "</span></span>";
		if (money.silver > 0) html += "<span class='silver'>" +parseInt( money.silver, 10) +" <span>" + Messages.get("market.js.common.text.price_silver") + "</span></span>";
		if (money.bronze > 0) html += "<span class='bronze'>" + parseInt(money.bronze, 10) + " <span>" + Messages.get("market.js.common.text.price_bronze") + "</span></span>";
		//if (money.gold > 0) html += "<span class='gold'>" + parseInt(money.gold, 10) + " <span>...</span></span>";
		//if (money.silver > 0) html += "<span class='silver'>" +parseInt( money.silver, 10) +" <span>...</span></span>";
		//if (money.bronze > 0) html += "<span class='bronze'>" + parseInt(money.bronze, 10) + " <span>...</span></span>";
		return html;
	};
	return Util;
}(BNS.Command, jQuery));

BNS.Ui = (function ($) {
	var Ui = {};
	function NumericInput (obj, callback) {
		this.ctx = $(obj);
		this.maxLength = this.ctx.attr("maxlength");
		this.bind(callback);
	}
	function isNumber(keyCode) {
		if ((keyCode >=65 && keyCode <=90 ) || (keyCode<48 || keyCode>57) && (keyCode<96 || keyCode>105) || (e.target.value.length >= maxLength)) {
			return false;
		}
		return true;
	}
	//ctrl + c, ctrl + v ......... ............ ......... ............
	NumericInput.prototype.bind = function (callback) {
//		var maxLength = this.maxLength;
		this.ctx.keydown(function (e) {
			var keyCode = e.keyCode;
			if (keyCode==46 || keyCode==8 || keyCode==9 || keyCode==27 || (keyCode==65 && e.ctrlKey===true) || (keyCode==67 && e.ctrlKey===true) || (keyCode==86 && e.ctrlKey===true) || (keyCode>=35 && keyCode<=39)) {
				return;
			}
			if ((keyCode >=65 && keyCode <=90 ) || (keyCode<48 || keyCode>57) && (keyCode<96 || keyCode>105)) {
				e.preventDefault();
			}
		});
		this.ctx.keyup(function (e) {
			callback(e);
		});
		this.ctx.keypress(function (e) {
			callback(e);
		});
	};
	Ui.numerics = function (objs, callback) {
		for (var i=0 ; i<objs.length ; i++)	 {
			new NumericInput(objs[i], callback);
		}
	};
	return Ui;
}(jQuery));
04/27/2016 16:41 blueaoi#2
Using that exact info, I've been able browse marketplace from my chrome browser, I'm still able to even during maintenance.
It only requires one token, which you can get trough any HTTP GET request sent from the game. I'm currently working on getting info about how long these tokens stay active and about getting/generating them, only found it for the 2 first bytes of it (mind you, it's 256 bytes long).
If you want a hint, take a look at the cookies.

Edit: I mean, accessing the mp to get prices, make searches, favorite items. I haven't been able to buy things so far yet.
04/28/2016 08:39 killzone#3
You need your account to logged in to buy outside the Game Browser. Thats How I see it.
04/29/2016 17:24 roanz#4
Yep, unfortunately the token only valid for a few hours.
It is possible to make clientless bot to obtain those tokens, it is quite simple, but my skills aren't good enough.

@[Only registered and activated users can see links. Click Here To Register...]:
any luck generating those tokens?

[Only registered and activated users can see links. Click Here To Register...]
04/30/2016 11:32 blueaoi#5
Quote:
Originally Posted by roanz View Post
Yep, unfortunately the token only valid for a few hours.
It is possible to make clientless bot to obtain those tokens, it is quite simple, but my skills aren't good enough.

@[Only registered and activated users can see links. Click Here To Register...]:
any luck generating those tokens?
Yeah, I'd say somewhere around 6 or 8 hours, even after you logged out of the game.
My skills aren't too great either so I wouldn't know xD but if you can get something working I'd be interested, my main purpose is being able to consistently get mp prices even when I'm in F8 without having to run wireshark/anything else of that kind before, best would be making my bns discord bot able to look things up. Only thing I miss for that is the damn token xD

Quote:
Originally Posted by killzone View Post
You need your account to logged in to buy outside the Game Browser. Thats How I see it.
Your account is kinda logged in trough said token, what makes me think that is the fact you can favorite an item and see the change in-game. You also get your own favorited list.
04/30/2016 15:20 killzone#6
I'll see if I can get the token from logging from the NCLauncher.
And with that, I think we can create a standalone emulator for the external market. (If its possible)
05/04/2016 16:14 killzone#7
Where: 000000000 (9 digit) is your unique ID.
05/26/2016 21:53 blueaoi#8
Ohh nice :)
Sadly exams and shit reduce my time to fiddle around with this :/
(also, the notifications system on this site is shit imo)
09/29/2016 01:24 The_Shape_Shifter#9
Any updates on this? I wanna pickup the 'project'
12/09/2016 21:12 Sobarius#10
Me too.