Closed azdafirmansyah closed 7 years ago
Hello @azdafirmansyah
Read the interface specification for details about the commands:
ftp://ftp.cenorm.be/CWA/CEN/WS-XFS/CWA15748/CWA15748-15-2008-July.pdf
OPEN_SHUTTER
and CLOSE_SHUTTER
will basically do what you expect, opening or closing the shutter. The Capabilities3.isShutterControl()
method indicates if the shutter is controlled implicitly by the service provider. If isShutterControl()
returns false
, the shutter must be explicitly controlled by the application.
As mentioned, the CIM interface specification gives you examples of some transaction flows in chapter 7. For example, the transaction flow for a OK transaction with explicit shutter control would be something like this:
Capabilities3.isItemsInsertedSensor()
)A CASH_IN
command will produce lots of execute and service events you must deal with, but here is some pseudo code which should give you clues:
CimService cimService = ...
// CASH_IN_START, etc. ...
XfsExecuteCommand<CimExecuteCommand> executeCommand = new XfsExecuteCommand<CimExecuteCommand>(cimService,
CimExecuteCommand.CASH_IN);
cimService.addCimServiceListener(new CimServiceListener() {
public void onItemsInserted() ...
public void onItemsTaken() ...
public void onItemsPresented() ...
});
executeCommand.execute(new XfsEventNotification() {
@Override
public void fireOperationCompleteEvent(WFSResult wfsResult) {
String method = "fireOperationCompleteEvent(WFSResult)";
try {
if (LOG.isDebugEnabled()) {
LOG.debug(method, "wfsResult=" + wfsResult);
}
XfsException.throwFor(wfsResult.getResult());
NoteNumberList3 noteNumberList3 = new NoteNumberList3(wfsResult.getResults());
noteNumberList3 = new NoteNumberList3(noteNumberList3); // copy for later use
System.out.println(noteNumberList3);
} catch (XfsException e) {
e.printStackTrace();
} finally {
XfsServiceManager.getInstance().free(wfsResult);
}
}
@Override
public void fireIntermediateEvent(WFSResult wfsResult) {
String method = "fireIntermediateEvent(WFSResult)";
if (LOG.isDebugEnabled()) {
LOG.debug(method, "wfsResult=" + wfsResult);
}
try {
CimMessage cimMessage = wfsResult.getEventID(CimMessage.class);
switch (cimMessage) {
case EXEE_CIM_CASHUNITERROR:
/* TODO */ break;
case EXEE_CIM_INPUT_P6:
/* TODO */ break;
case EXEE_CIM_INPUTREFUSE:
/* TODO */ break;
case EXEE_CIM_NOTEERROR:
/* TODO */ break;
case EXEE_CIM_SUBCASHIN:
/* TODO */ break;
case EXEE_CIM_INFO_AVAILABLE:
/* TODO */ break;
case EXEE_CIM_INSERTITEMS:
/* TODO */ break;
default:
throw new IllegalArgumentException(cimMessage.toString());
}
} finally {
XfsServiceManager.getInstance().free(wfsResult);
}
}
});
ATTENTION:
For example new NoteNumberList3(wfsResult.getResults())
create a java object from native memory. The call XfsServiceManager.free(WFSResult)
will release this memory. So if you want to use this information outside of the event processing method, use the copy constructor. Otherwise you may end up accessing already freed memory and your JVM crashes.
Best regards, Andreas Fagschlunger
Hello @AndreasFagschlunger,
I follow your code and get the following error :
java.lang.NullPointerException: Pointer points to NULL
at at.o2xfs.win32.Pointer.buffer(Pointer.java:84)
at at.o2xfs.win32.Type.assignBuffer(Type.java:44)
at at.o2xfs.xfs.cim.v3_00.NoteNumberList3.
but wfsResult.getResult() is nut null.
Any suggest ?
Regards, Azda Firmansyah
Try System.out.println(wfsResult.getResults())
, the object Pointer
may not be null, but the address it's pointing to is likely to point to NULL
. This is also valid according to the specification:
If the whole input was refused then this parameter will be NULL and one or more WFS_EXEE_CIM_INPUTREFUSE events will be generated.
So check against a (native) NULL-Pointer:
if(Pointer.NULL.equals(wfsResult.getResults())) ...
Hi @AndreasFagschlunger ,
I try the following OK Transaction flow in doc. But still cannot get event any item Inserted.
please review my code : https://drive.google.com/file/d/0B3NRikF5MB_2ZFk3c3h4MTBwc3c/view?usp=sharing
I just want to try:
Please advice.
Regards, Azda Firmansyah
The event handling must be implemented like in CdmService.fireServiceEvent(WFSResult)
, of course with the right CIM events. Also notice, SRVE_CIM_ITEMSINSERTED
is only fired if Capabilities3.isItemsInsertedSensor()
returns true. Otherwise the customer has to confirm completion (e.g., press button) to continue transaction with CASH_IN
command.
Hi @AndreasFagschlunger,
I still get false while check the value of Capabilities3.isItemsInsertedSensor().
I do check the value in fireIntermediateEvent(WFSResult wfsResult)
and fireOperationCompleteEvent
function
Capabilities3 capabilities3 = new Capabilities3(wfsResult.getResults()); System.out.println(capabilities3.isItemsInsertedSensor());
Also get return EXEE_CIM_INPUTREFUSE
from CimMessage
CimMessage cimMessage = wfsResult.getEventID(CimMessage.class);
Here is my snippet code :
public void fireIntermediateEvent(WFSResult wfsResult) { Capabilities3 capabilities3 = new Capabilities3(wfsResult.getResults()); System.out.println(capabilities3.isItemsInsertedSensor());
What I do in this step are :
capabilities3.isItemsInsertedSensor()
return false
and get EXEE_CIM_INPUTREFUSE
from CimMessagePlease advice.
Regards, Azda Firmansyah
Hello @azdafirmansyah
What does Capabilities3.isShutterControl
return? And if Capabilities3.isItemsInsertedSensor()
returns false
, you have to wait for a user interaction after CASH_IN_START
, e.g.:
System.out.println("Please insert money, press ENTER to continue...");
new Scanner(System.in).nextLine();
System.out.println("Executing CASH_IN ...");
And this is dangerous:
public void fireIntermediateEvent(WFSResult wfsResult) {
Capabilities3 capabilities3 = new Capabilities3(wfsResult.getResults());
System.out.println(capabilities3.isItemsInsertedSensor());
The fireIntermediateEvent
method is called when an execute event occurs. This events may occur during execution of your command and are specific to the command you execute. So you have to check for the right CimMessage
like in my example the last day. e.g.
try {
CimMessage cimMessage = wfsResult.getEventID(CimMessage.class);
switch (cimMessage) {
case EXEE_CIM_CASHUNITERROR:
/* TODO */ break;
case EXEE_CIM_INPUT_P6:
/* TODO */ break;
case EXEE_CIM_INPUTREFUSE:
Reason reason = new XfsWord<>(Reason.class, wfsResult.getResults());
System.out.println("Reason for refusing part of the amount: " + reason);
break;
Regards, Andreas Fagschlunger
Hi @AndreasFagschlunger,
Are you sure to wait for a user interaction after CASH_IN_START
like you mention above ?
I print the result of EXEE_CIM_INPUTREFUSE
, here is what i get :
Reason for refusing part of the amount: INVALIDBILL
Can you review my code ? maybe something wrong in my code https://drive.google.com/file/d/0B3NRikF5MB_2V2dOMFJlb2haWkk/view?usp=sharing
Regards, Azda Firmansyah
Hi @azdafirmansyah
If Capabilities3.isItemsInsertedSensor()
returns false, you have to wait until a customer inserts money and continues the transaction. This also means, no service event ITEMSINSERTED
event will occur.
So your problem now is, that the cash in command works but reports INVALIDBILL
? The description of INVALIDBILL
is as follows:
Recognition of the items took place, but one or more of the items are invalid.
Is your ATM configured to accept test bills or do you use real bills? Can you test recognition with a vendor app? Unfortunately this issue lies beneath XFS and must be checked with your ATM vendor. You may find some information in the vendor logs. Or try to use real and dummy bills, maybe the configuration of your ATM is wrong.
Hi @AndreasFagschlunger,
If Capabilities3.isItemsInsertedSensor() returns false, you have to wait until a customer inserts money and continues the transaction. This also means, no service event ITEMSINSERTED event will occur. ---> I use CASH_IN command, when shutter open I put money inside shutter and than shutter will close automatically. I think when use this flow no need to wait customer inside money, because already do that
Is your ATM configured to accept test bills or do you use real bills? Can you test recognition with a vendor app? Unfortunately this issue lies beneath XFS and must be checked with your ATM vendor. You may find some information in the vendor logs. Or try to use real and dummy bills, maybe the configuration of your ATM is wrong. ---> Already success test using vendor tools with real money
Is it my code correct ?
Regards, Azda Firmansyah
Hi @azdafirmansyah
It's a bit strange, isItemsInsertedSensor
should return true
if the shutter closes one you inserted money. So the ATM waits a long time when you don't insert money but immediately closes if money is inserted? That should also mean you don't have to execute OPEN_SHUTTER
command because the shutter is automatically opened during CASH_IN_START
?
I can't access Google drive right now, since I'm behind a firewall. So I must check the code later. But it's strange you get INVALIDBILL
when the vendor app does recognize the money. Try looking into vendor logs if you find some, maybe the leave a clue what's really wrong.
Hi @AndreasFagschlunger,
The shutter automatically open during CASH_IN command (not CASH_IN _START).
Here is what step I do :
Here is my code : ` CimService cimService = (CimService) xfsServiceManager.openAndRegister("CIM", CimService.class);
cimService.addCimServiceListener(new CimServiceListener() {
@Override
public void onCimTellerInfoChanged(int tellerId) {
// TODO Auto-generated method stub
System.out.println("onCimTellerInfoChanged : " + tellerId);
}
@Override
public void onCimShutterStatusChanged(
ShutterStatusChanged3_30 shutterStatusChanged) {
// TODO Auto-generated method stub
System.out.println("onCimShutterStatusChanged : "
+ shutterStatusChanged);
}
@Override
public void onCimSafeDoorOpen() {
// TODO Auto-generated method stub
System.out.println("onCimSafeDoorOpen : ");
}
@Override
public void onCimSafeDoorClosed() {
// TODO Auto-generated method stub
System.out.println("onCimSafeDoorClosed : ");
}
@Override
public void onCimPowerSaveChange(
PowerSaveChange3_10 powerSaveChange) {
// TODO Auto-generated method stub
System.out.println("onCimPowerSaveChange : "
+ powerSaveChange);
}
@Override
public void onCimMediaDetected(
Optional<ItemPosition3> itemPosition) {
// TODO Auto-generated method stub
System.out.println("onCimMediaDetected : " + itemPosition);
}
@Override
public void onCimItemsTaken(at.o2xfs.xfs.cim.Position position) {
// TODO Auto-generated method stub
System.out.println("onCimItemsTaken : " + position);
}
@Override
public void onCimItemsPresented() {
// TODO Auto-generated method stub
System.out.println("onCimItemsPresented : ");
}
@Override
public void onCimItemsInsert(at.o2xfs.xfs.cim.Position position) {
// TODO Auto-generated method stub
System.out.println("onCimItemsInsert : " + position);
}
@Override
public void onCimDevicePosition(
DevicePosition3_10 devicePosition) {
// TODO Auto-generated method stub
System.out.println("onCimDevicePosition : "+ devicePosition);
}
@Override
public void onCimCountsChanged(CountsChanged3 countsChanged) {
// TODO Auto-generated method stub
System.out.println("onCimCountsChanged : " + countsChanged);
}
@Override
public void onCimCashUnitThreshold(CashIn3 cashIn3) {
// TODO Auto-generated method stub
System.out.println("onCimCashUnitThreshold : " + cashIn3);
}
@Override
public void onCimCashUnitInfoChanged(CashIn3 cashIn3) {
// TODO Auto-generated method stub
System.out.println("onCimCashUnitInfoChanged : " + cashIn3);
}
});
Capabilities3 capabilities1 = cimService.getCapabilities();
Set<at.o2xfs.xfs.cim.Position> pos = capabilities1.getPositions();
Iterator itr = pos.iterator();
while (itr.hasNext()) {
at.o2xfs.xfs.cim.Position sPosition = (at.o2xfs.xfs.cim.Position)itr.next();
String sName = sPosition.name();
System.out.println(sName);
}
CashInStart3 cashInStart3 = new CashInStart3.Builder()
.inputPosition(at.o2xfs.xfs.cim.Position.INFRONT)
.outputPosition(at.o2xfs.xfs.cim.Position.OUTREAR).build();
XfsExecuteCommand<CimExecuteCommand> cashInStartCommand = new XfsExecuteCommand<CimExecuteCommand>(
cimService, CimExecuteCommand.CASH_IN_START, cashInStart3);
WFSResult wfsResultCashInStart = null;
try {
wfsResultCashInStart = cashInStartCommand.call();
} catch (XfsException e) {
e.printStackTrace();
} finally {
if (wfsResultCashInStart != null) {
xfsServiceManager.free(wfsResultCashInStart);
}
}
XfsExecuteCommand<CimExecuteCommand> cashInCommand = new XfsExecuteCommand<CimExecuteCommand>(
cimService, CimExecuteCommand.CASH_IN, cashInStart3);
cashInCommand.execute(new XfsEventNotification() {
@Override
public void fireOperationCompleteEvent(WFSResult wfsResult) {
String method = "fireOperationCompleteEvent(WFSResult)";
Capabilities3 capabilities3 = new Capabilities3(wfsResult.getResults());
System.out.println(capabilities3.isItemsInsertedSensor());
try {
XfsException.throwFor(wfsResult.getResult());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
XfsServiceManager.getInstance().free(wfsResult);
}
}
@Override
public void fireIntermediateEvent(WFSResult wfsResult) {
try {
CimMessage cimMessage = wfsResult.getEventID(CimMessage.class);
switch (cimMessage) {
case EXEE_CIM_CASHUNITERROR:
/* TODO */break;
case EXEE_CIM_INPUT_P6:
/* TODO */break;
case EXEE_CIM_INPUTREFUSE:
XfsWord<Reason> reason = new XfsWord<>(Reason.class, wfsResult.getResults());
System.out.println("Reason for refusing part of the amount: " + reason.get().toString());
/* TODO */break;
case EXEE_CIM_NOTEERROR:
/* TODO */break;
case EXEE_CIM_SUBCASHIN:
/* TODO */break;
case EXEE_CIM_INFO_AVAILABLE:
/* TODO */break;
case EXEE_CIM_INSERTITEMS:
/* TODO */break;
default:
throw new IllegalArgumentException(cimMessage
.toString());
}
} finally {
XfsServiceManager.getInstance().free(wfsResult);
}
}
});`
Regards, Azda Firmansyah
Ok, I mixed isShutterControl
with isItemsInsertedSensor
. Your ATM's shutter is implicitly control, therefore isShutterControl
returns true
. isItemsInsertedSensor
will only inform you, if a inserted event is generated or not. What is obviously wrong is the code in fireOperationCompleteEvent
:
public void fireOperationCompleteEvent(WFSResult wfsResult) {
String method = "fireOperationCompleteEvent(WFSResult)";
Capabilities3 capabilities3 = new Capabilities3(wfsResult.getResults());
System.out.println(capabilities3.isItemsInsertedSensor());
The output parameter of CASH_IN
is a pointer to WFSCIMNOTENUMBERLIST
, where NULL
is also possible. So something like this should work:
public void fireOperationCompleteEvent(WFSResult wfsResult) {
String method = "fireOperationCompleteEvent(WFSResult)";
if (LOG.isDebugEnabled()) {
LOG.debug(method, "wfsResult=" + wfsResult);
}
try {
XfsException.throwFor(wfsResult.getResult());
if(Pointer.NULL.equals(wfsResult.getResults())) {
System.out.println("Whole input was refused");
} else {
NoteNumberList3 noteNumberList = new NoteNumberList3(new NoteNumberList3(wfsResult.getResults()));
System.out.println(noteNumberList);
}
} catch (XfsException e) {
e.printStackTrace();
} finally {
XfsServiceManager.getInstance().free(wfsResult);
}
}
If your ATM recognizes some bills, you should get a NoteNumberList3
object.
Hi @AndreasFagschlunger,
Now I can recognize some bills in NoteNumberList3. I have few question :
is it correct way or not if I execute CASH_IN_END
command inside fireOperationCompleteEvent
?
for example after get bill info :
NoteNumber3[] noteNumber3 = noteNumberList.getNoteNumber(); .... XfsExecuteCommand
cashEndCommand = new XfsExecuteCommand ( cimService, CimExecuteCommand.CASH_IN_END, cashInStart3); WFSResult wfsResultCashEnd = null; try { wfsResultCashEnd = cashEndCommand.call(); ....
When I execute CASH_IN_END
command, I get "Waiting ..." from LOG like below
2017-03-15 09:48:31,555 DEBUG [MessageHandler] at.o2xfs.xfs.XfsAPI: wfsAsyncExecute(HSERVICE, DWORD, Type, DWORD, HWND): hService=1,dwCommand=1303,lpCmdData=at.o2xfs.xfs.cim.v3_00.CashInStart3@1710f1a[tellerID=0,useRecycleUnits=false,outputPosition=OUTREAR,inputPosition=INFRONT],dwTimeOut=0,hWnd=18070800 2017-03-15 09:48:31,555 DEBUG [MessageHandler] at.o2xfs.xfs.service.cmd.XfsCallable: call(): Waiting ... what should I "waiting..." for ? and what is mean "waiting..." in this LOG ? The money already inside cassette
how to get status in CASH_IN_END
command ? I mean like success deposit or etc.
seems like after execute wfsResultCashEnd = cashEndCommand.call();
, the next line not execeute because get "waiting..." in Log
How to get one of event in cimService.addCimServiceListener(new CimServiceListener() {
like below
cimService.addCimServiceListener(new CimServiceListener() {
@Override
public void onCimShutterStatusChanged(
ShutterStatusChanged3_30 shutterStatusChanged) {
System.out.println("onCimShutterStatusChanged : "
+ shutterStatusChanged);
}
@Override
public void onCimSafeDoorOpen() {
System.out.println("onCimSafeDoorOpen : ");
}
@Override
public void onCimSafeDoorClosed() {
System.out.println("onCimSafeDoorClosed : ");
}
@Override
public void onCimItemsTaken(at.o2xfs.xfs.cim.Position position) {
System.out.println("onCimItemsTaken : " + position);
}
@Override
public void onCimItemsPresented() {
System.out.println("onCimItemsPresented : ");
}
@Override
public void onCimItemsInsert(at.o2xfs.xfs.cim.Position position) {
System.out.println("onCimItemsInsert : " + position);
}
....
});
Regards, Azda Firmansyah
Hello @azdafirmansyah
It's not recommended to execute another command during event processing (methods in XfsEventNotification
). Waiting for a result in fireOperationCompleteEvent
will not work at all, because the Thread is blocked. As I mentioned in Issue #42, I would suggest do create a state machine. In fireOperationCompleteEvent
you just set a boolean and notify the Thread about the state change. Check EjectCardCommand
for details.
Best regards, Andreas Fagschlunger
Hi @AndreasFagschlunger,
Thanks for your explanation. How about my number 4 question above ?
Regards, Azda Firmansyah
Hello @azdafirmansyah
CimService
must overwrite fireServiceEvent(WFSResult)
and handle all SRVE_
events accordingly, take CdmService
as an example.
Best regards, Andreas Fagschlunger
Thanks @AndreasFagschlunger
Be sure to check out the latest commit d737af6 where I added a untested version of various CIM commands.
@AndreasFagschlunger Hello, I am quite new to all of this im just looking around for now and learning python. I read about ATM malware called tyupkin, it would infect an atm machine then tell it to dispense all of the notes. I also read about a black box attack where a raspberry pi was connected via usb and a command was sent to do the same thing. Do you know how this works? Is it really as simple as creating a java script that send the correct command to the correct device?
haha sounds wrong when you read it, java file* sounds better
Hello @Shroudedd! For the future, you can create a issue and tag it as question, since it is off topic. But anyway, the CEN/XFS API doesn't deal with security. So if you manage to run your own executable (C, Java, etc.) on an ATM, it will dispense and present cash. But usually an ATM is hardened enough so you shouln't be able to copy your "malware" and execute it. The Raspberry PI thing targets directly to the hardware. So you plug the cash dispenser to you raspberry (or other computer) directly and try to dispense/present cash directly. This would be possible if the USB communication isn't encrypted, which it usually is. Also you need deep knowledge of the hardware you're dealing with, since every cash dispenser (and firmware) is different.
Best regards, Andreas Fagschlunger
Thank you for the quick reply, it went to a separate folder for some reason and I just now saw your email. Yes I saw a video on youtube of someone showing how they unplug the dispenser and plug it into a black box and it works. The XFS documentation covers all the proper commands and format but what im confused is how exactly are the commands send? like through a terminal? Plugging the dispenser into a laptop would show it as a connected device, but through what means are the commands sent?
On Wed, Apr 11, 2018 at 1:47 AM, AndreasFagschlunger < notifications@github.com> wrote:
Hello @Shroudedd https://github.com/Shroudedd! For the future, you can create a issue and tag it as question, since it is off topic. But anyway, the CEN/XFS API doesn't deal with security. So if you manage to run your own executable (C, Java, etc.) on an ATM, it will dispense and present cash. But usually an ATM is hardened enough so you shouln't be able to copy your "malware" and execute it. The Raspberry PI thing targets directly to the hardware. So you plug the cash dispenser to you raspberry (or other computer) directly and try to dispense/present cash directly. This would be possible if the USB communication isn't encrypted, which it usually is. Also you need deep knowledge of the hardware you're dealing with, since every cash dispenser (and firmware) is different.
Best regards, Andreas Fagschlunger
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-380376425, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF-JMtmz41SSCzJlsbzshPa0phERBks5tncM3gaJpZM4MaxZs .
If you say they plug it into a black box, I'm pretty sure this is the second scenario where CEN/XFS isn't involved. The just communicate directly with the dispenser (USB). If their isn't any encryption, you just need to send the right commands (or bits and bytes). That's what I meant by needing deep knowledge of the hardware. There is no standard on how the XFS Service Provider communicates with the hardware. So communicating with the hardware directly over USB is something very low level and device specific.
I understand but if its plugged directly into the device, you still need to send xfs commands right? Because that's the only thing that the device accepts as a command to dispense? Are you aware of any resources online I could look at that explains this subject?
On Fri, Apr 13, 2018, 1:43 AM AndreasFagschlunger notifications@github.com wrote:
If you say they plug it into a black box, I'm pretty sure this is the second scenario where CEN/XFS isn't involved. The just communicate directly with the dispenser (USB). If their isn't any encryption, you just need to send the right commands (or bits and bytes). That's what I meant by needing deep knowledge of the hardware. There is no standard on how the XFS Service Provider communicates with the hardware. So communicating with the hardware directly over USB is something very low level and device specific.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381067719, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF5EJkPLRRwl31k1xtcJmqFi6zLLKks5toGU-gaJpZM4MaxZs .
No, as I said before the protocol used to communicate with the dispenser over USB etc. is not standardized and beyond the scope of XFS. It is a proprietary protocol specific to the hardware used. As of resources, you can ask Google about jackpotting attacks. Here is what I found: https://krebsonsecurity.com/2018/01/first-jackpotting-attacks-hit-u-s-atms/
Thank you for the response and taking time out of your day to explain this to me. I'm sorry I'm having difficulty understanding it still, the atm software communicate with the xfs manager which sends commands through to the device service provider which then sends the command to the device, am I right? Xfsmanager>>api/spi>>sp>>device? So by bypassing the chain and plugging directly into the device, why would I not still send the xfs command? Does the service provider translate the xfs command and send something else to the device? Also, how do you go about figuring out the correct bytes to send if you plug in directly? Do I have to find the sp.dll and look inside of that?
On Sat, Apr 14, 2018, 12:28 AM AndreasFagschlunger notifications@github.com wrote:
No, as I said before the protocol used to communicate with the dispenser over USB etc. is not standardized and beyond the scope of XFS. It is a proprietary protocol specific to the hardware used. As of resources, you can ask Google about jackpotting attacks. Here is what I found: https://krebsonsecurity.com/2018/01/first-jackpotting-attacks-hit-u-s-atms/
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381310269, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF51N_CGOSPUhjlsNenoyePkBjniKks5toaU2gaJpZM4MaxZs .
First off, yes the SP sends something else to the device. See, CEN/XFS is a standardized C-API. So it is a function call with defined parameters on a defined library (msxfs.dll). A hardware doesn't has libraries, it has cables (or antennas) and communicates through them. So the whole idea behind XFS is, that you don't want to deal with this hardware specific things. You know it's a dispenser, so you want it to dispense something. You don't care if the dispenser is from NCR or Diebold-Nixdorf and how it is connected to the PC (USB, Serial-Port, whatever). You buy an ATM which supports XFS, you know there is a msxfs.dll installed, you know which functions to call to dispense cash. The rest is not your concern, the SP from NCR, Diebold-Nixdorf, etc. knows how to process your request and howto tell the dispenser to do the things you requested.
That said, the only way you can use XFS commands on your "black box" is, that your black box has a suitable XFS SP installed.
And if you don't have documents about how something works, you have to use reverse engineering. For example, you can trace the USB connection and see which bytes are send in which situation etc. But I'm not an hacker, so I don't know how such things are usually done.
Okay that cleared it up for me thank you. So if it was a black box attack the attacker would have to know the specific device specs, alot harder of a challenge than just installing malware that uses the xfs right? Thanks man!
On Sat, Apr 14, 2018 at 3:23 PM, AndreasFagschlunger < notifications@github.com> wrote:
First off, yes the SP sends something else to the device. See, CEN/XFS is a standardized C-API. So it is a function call with defined parameters on a defined library (msxfs.dll). A hardware doesn't has libraries, it has cables (or antennas) and communicates through them. So the whole idea behind XFS is, that you don't want to deal with this hardware specific things. You know it's a dispenser, so you want it to dispense something. You don't care if the dispenser is from NCR or Diebold-Nixdorf and how it is connected to the PC (USB, Serial-Port, whatever). You buy an ATM which supports XFS, you know there is a msxfs.dll installed, you know which functions to call to dispense cash. The rest is not your concern, the SP from NCR, Diebold-Nixdorf, etc. knows how to process your request and howto tell the dispenser to do the things you requested.
That said, the only way you can use XFS commands on your "black box" is, that your black box has a suitable XFS SP installed.
And if you don't have documents about how something works, you have to use reverse engineering. For example, you can trace the USB connection and see which bytes are send in which situation etc. But I'm not an hacker, so I don't know how such things are usually done.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381364835, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF1aH7yibqk_hiMby6i5f9Btf31Fdks5tonbEgaJpZM4MaxZs .
Im pretty familiar with python but I dont think something like this could be accomplished with python, can it? So i am in the process of learning c++ right now. Also, what is the XFS sdk for?
On Sat, Apr 14, 2018 at 9:48 PM, Yury Rashnikov yury.rashnikov@gmail.com wrote:
Okay that cleared it up for me thank you. So if it was a black box attack the attacker would have to know the specific device specs, alot harder of a challenge than just installing malware that uses the xfs right? Thanks man!
On Sat, Apr 14, 2018 at 3:23 PM, AndreasFagschlunger < notifications@github.com> wrote:
First off, yes the SP sends something else to the device. See, CEN/XFS is a standardized C-API. So it is a function call with defined parameters on a defined library (msxfs.dll). A hardware doesn't has libraries, it has cables (or antennas) and communicates through them. So the whole idea behind XFS is, that you don't want to deal with this hardware specific things. You know it's a dispenser, so you want it to dispense something. You don't care if the dispenser is from NCR or Diebold-Nixdorf and how it is connected to the PC (USB, Serial-Port, whatever). You buy an ATM which supports XFS, you know there is a msxfs.dll installed, you know which functions to call to dispense cash. The rest is not your concern, the SP from NCR, Diebold-Nixdorf, etc. knows how to process your request and howto tell the dispenser to do the things you requested.
That said, the only way you can use XFS commands on your "black box" is, that your black box has a suitable XFS SP installed.
And if you don't have documents about how something works, you have to use reverse engineering. For example, you can trace the USB connection and see which bytes are send in which situation etc. But I'm not an hacker, so I don't know how such things are usually done.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381364835, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF1aH7yibqk_hiMby6i5f9Btf31Fdks5tonbEgaJpZM4MaxZs .
I just installed the XFS sdk on my computer, thinking it was an actual SDK to develop your own xfs compliant applications, but as far as i can tell, all it installed was the dll is that right? Sorry for blowing you up with all these questions. I spend hours researching this stuff and its just nice having found someone who is knowledgeable on this topic lol.
On Sat, Apr 14, 2018 at 9:52 PM, Yury Rashnikov yury.rashnikov@gmail.com wrote:
Im pretty familiar with python but I dont think something like this could be accomplished with python, can it? So i am in the process of learning c++ right now. Also, what is the XFS sdk for?
On Sat, Apr 14, 2018 at 9:48 PM, Yury Rashnikov yury.rashnikov@gmail.com wrote:
Okay that cleared it up for me thank you. So if it was a black box attack the attacker would have to know the specific device specs, alot harder of a challenge than just installing malware that uses the xfs right? Thanks man!
On Sat, Apr 14, 2018 at 3:23 PM, AndreasFagschlunger < notifications@github.com> wrote:
First off, yes the SP sends something else to the device. See, CEN/XFS is a standardized C-API. So it is a function call with defined parameters on a defined library (msxfs.dll). A hardware doesn't has libraries, it has cables (or antennas) and communicates through them. So the whole idea behind XFS is, that you don't want to deal with this hardware specific things. You know it's a dispenser, so you want it to dispense something. You don't care if the dispenser is from NCR or Diebold-Nixdorf and how it is connected to the PC (USB, Serial-Port, whatever). You buy an ATM which supports XFS, you know there is a msxfs.dll installed, you know which functions to call to dispense cash. The rest is not your concern, the SP from NCR, Diebold-Nixdorf, etc. knows how to process your request and howto tell the dispenser to do the things you requested.
That said, the only way you can use XFS commands on your "black box" is, that your black box has a suitable XFS SP installed.
And if you don't have documents about how something works, you have to use reverse engineering. For example, you can trace the USB connection and see which bytes are send in which situation etc. But I'm not an hacker, so I don't know how such things are usually done.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381364835, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF1aH7yibqk_hiMby6i5f9Btf31Fdks5tonbEgaJpZM4MaxZs .
There are ways to access DLLs in Python, just Google for it, e.g. https://stackoverflow.com/questions/252417/how-can-i-use-a-dll-file-from-python The default location for XFS SDK is C:/Program Files (x86)/Common Files/XFS/SDK. You can take a look at xfs-sdk.ps1, it downloads all SDKs and unpacks them. The msxfs.dll which gets installed is the default implementation for the XFS Manager.
Thank you, I'm going to try and do it with c++ though, will be a good learning experience. How I understand it std::cout uses the standard namespace and cout is the output function, so xfs would it be xfs::xfscommand?
On Sun, Apr 15, 2018, 2:17 AM AndreasFagschlunger notifications@github.com wrote:
There are ways to access DLLs in Python, just Google for it, e.g. https://stackoverflow.com/questions/252417/how-can-i-use-a-dll-file-from-python The default location for XFS SDK is C:/Program Files (x86)/Common Files/XFS/SDK. You can take a look at xfs-sdk.ps1 https://github.com/AndreasFagschlunger/O2Xfs/blob/develop/xfs-sdk.ps1, it downloads all SDKs and unpacks them. The msxfs.dll which gets installed is the default implementation for the XFS Manager.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381392056, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaFxVX8lK2zAueYEE-LIpbfYrEOzaPks5toxAegaJpZM4MaxZs .
Something along those lines?
On Sun, Apr 15, 2018, 1:02 PM Yury Rashnikov yury.rashnikov@gmail.com wrote:
Thank you, I'm going to try and do it with c++ though, will be a good learning experience. How I understand it std::cout uses the standard namespace and cout is the output function, so xfs would it be xfs::xfscommand?
On Sun, Apr 15, 2018, 2:17 AM AndreasFagschlunger < notifications@github.com> wrote:
There are ways to access DLLs in Python, just Google for it, e.g. https://stackoverflow.com/questions/252417/how-can-i-use-a-dll-file-from-python The default location for XFS SDK is C:/Program Files (x86)/Common Files/XFS/SDK. You can take a look at xfs-sdk.ps1 https://github.com/AndreasFagschlunger/O2Xfs/blob/develop/xfs-sdk.ps1, it downloads all SDKs and unpacks them. The msxfs.dll which gets installed is the default implementation for the XFS Manager.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381392056, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaFxVX8lK2zAueYEE-LIpbfYrEOzaPks5toxAegaJpZM4MaxZs .
Do you have any sample code that shows using and sending an xfs command to any device that I can just look at and study instead of bothering you?
On Sun, Apr 15, 2018, 1:03 PM Yury Rashnikov yury.rashnikov@gmail.com wrote:
Something along those lines?
On Sun, Apr 15, 2018, 1:02 PM Yury Rashnikov yury.rashnikov@gmail.com wrote:
Thank you, I'm going to try and do it with c++ though, will be a good learning experience. How I understand it std::cout uses the standard namespace and cout is the output function, so xfs would it be xfs::xfscommand?
On Sun, Apr 15, 2018, 2:17 AM AndreasFagschlunger < notifications@github.com> wrote:
There are ways to access DLLs in Python, just Google for it, e.g. https://stackoverflow.com/questions/252417/how-can-i-use-a-dll-file-from-python The default location for XFS SDK is C:/Program Files (x86)/Common Files/XFS/SDK. You can take a look at xfs-sdk.ps1 https://github.com/AndreasFagschlunger/O2Xfs/blob/develop/xfs-sdk.ps1, it downloads all SDKs and unpacks them. The msxfs.dll which gets installed is the default implementation for the XFS Manager.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381392056, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaFxVX8lK2zAueYEE-LIpbfYrEOzaPks5toxAegaJpZM4MaxZs .
I used your script to install all the sdk, I found the header files that i need to use int he c program. I think thats what I was looking for. Now just to figure out the syntax
On Sun, Apr 15, 2018 at 1:06 PM, Yury Rashnikov yury.rashnikov@gmail.com wrote:
Do you have any sample code that shows using and sending an xfs command to any device that I can just look at and study instead of bothering you?
On Sun, Apr 15, 2018, 1:03 PM Yury Rashnikov yury.rashnikov@gmail.com wrote:
Something along those lines?
On Sun, Apr 15, 2018, 1:02 PM Yury Rashnikov yury.rashnikov@gmail.com wrote:
Thank you, I'm going to try and do it with c++ though, will be a good learning experience. How I understand it std::cout uses the standard namespace and cout is the output function, so xfs would it be xfs::xfscommand?
On Sun, Apr 15, 2018, 2:17 AM AndreasFagschlunger < notifications@github.com> wrote:
There are ways to access DLLs in Python, just Google for it, e.g. https://stackoverflow.com/questions/252417/how-can-i- use-a-dll-file-from-python The default location for XFS SDK is C:/Program Files (x86)/Common Files/XFS/SDK. You can take a look at xfs-sdk.ps1 https://github.com/AndreasFagschlunger/O2Xfs/blob/develop/xfs-sdk.ps1, it downloads all SDKs and unpacks them. The msxfs.dll which gets installed is the default implementation for the XFS Manager.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381392056, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaFxVX8lK2zAueYEE-LIpbfYrEOzaPks5toxAegaJpZM4MaxZs .
Why not using O²Xfs? Java is easy to understand and examples are already there. But either way, you can take a look at the C++ sources for at.o2xfs.xfs.dll: https://github.com/AndreasFagschlunger/O2Xfs/blob/develop/at.o2xfs.xfs/src/at.o2xfs.xfs.dll/cpp/at.o2xfs.xfs.cpp https://github.com/AndreasFagschlunger/O2Xfs/blob/develop/at.o2xfs.xfs/src/at.o2xfs.xfs.dll/cpp/MessageHandler.cpp
Just ignore the Java/JNI parts and focus on the parts using XFS-API. The DLL must create a message window, load the msxfs.dll, etc. otherwise you maybe take a look at this code:
https://github.com/sebastianscatularo/freexfs/tree/master/Samples/WosaXFSTest20100106
And read the CEN/XFS API documentation, at least Part 1:
https://www.cen.eu/work/areas/ICT/eBusiness/Pages/CWA16926.aspx
Okay cool thanks. Reason I want to do it with c++ is it's a harder language and I want to learn hard ones first then the rest
On Sun, Apr 15, 2018, 2:37 PM AndreasFagschlunger notifications@github.com wrote:
Why not using O²Xfs? Java is easy to understand and examples are already there. But either way, you can take a look at the C++ sources for at.o2xfs.xfs.dll:
Just ignore the Java/JNI parts and focus on the parts using XFS-API. The DLL must create a message window, load the msxfs.dll, etc. otherwise you maybe take a look at this code:
https://github.com/sebastianscatularo/freexfs/tree/master/Samples/WosaXFSTest20100106
And read the CEN/XFS API documentation, at least Part 1:
https://www.cen.eu/work/areas/ICT/eBusiness/Pages/CWA16926.aspx
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381440067, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF0zCwKdQRaoJqSEWgGKy_fKx1z3Oks5to722gaJpZM4MaxZs .
Hey Andreas, another quick question; I think the blackbox method connecting directly to the dispenser is the harder one because of the encryption like you said and because I would need specific sp information correct? Take a look at this https://youtu.be/Uxd0TRdE6sw What are they plugging into? Its an ethernet port but is it just like the ethernet port on the back of my tower?
On Sun, Apr 15, 2018 at 5:56 PM, Yury Rashnikov yury.rashnikov@gmail.com wrote:
Okay cool thanks. Reason I want to do it with c++ is it's a harder language and I want to learn hard ones first then the rest
On Sun, Apr 15, 2018, 2:37 PM AndreasFagschlunger < notifications@github.com> wrote:
Why not using O²Xfs? Java is easy to understand and examples are already there. But either way, you can take a look at the C++ sources for at.o2xfs.xfs.dll: https://github.com/AndreasFagschlunger/O2Xfs/ blob/develop/at.o2xfs.xfs/src/at.o2xfs.xfs.dll/cpp/at.o2xfs.xfs.cpp https://github.com/AndreasFagschlunger/O2Xfs/ blob/develop/at.o2xfs.xfs/src/at.o2xfs.xfs.dll/cpp/MessageHandler.cpp
Just ignore the Java/JNI parts and focus on the parts using XFS-API. The DLL must create a message window, load the msxfs.dll, etc. otherwise you maybe take a look at this code:
https://github.com/sebastianscatularo/freexfs/tree/master/Samples/ WosaXFSTest20100106
And read the CEN/XFS API documentation, at least Part 1:
https://www.cen.eu/work/areas/ICT/eBusiness/Pages/CWA16926.aspx
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-381440067, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF0zCwKdQRaoJqSEWgGKy_fKx1z3Oks5to722gaJpZM4MaxZs .
This is obviously scenario one. As I said, CEN/XFS doesn't cover security aspects. So if you manage to start your own executable on an ATM where XFS is installed, it willingly dispenses all the money you ask for - it doesn't even need administrator privileges.
You literally see that they using some kind of exploit to get access to the operating system and then copy and start their ATM_XFS.exe.
I get what they're doing I just didn't get how they were transferring the file over through ethernet. After further digging it looks like they connected the raspberry pi to the local network and then ssh'd to it and through and unpatched xp exploit opened a reverse shell. Now the part I can't figure out is how would then find the ethernet ip address of the atm..
On Tue, Apr 17, 2018, 11:20 PM AndreasFagschlunger notifications@github.com wrote:
This is obviously scenario one. As I said, CEN/XFS doesn't cover security aspects. So if you manage to start your own executable on an ATM where XFS is installed, it willingly dispenses all the money you ask for - it doesn't even need administrator privileges.
You literally see that they using some kind of exploit to get access to the operating system and then copy and start their ATM_XFS.exe.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/AndreasFagschlunger/O2Xfs/issues/43#issuecomment-382275632, or mute the thread https://github.com/notifications/unsubscribe-auth/AjaaF1R_svyEMvKL5PuVrphrXOZFeUM0ks5tpttCgaJpZM4MaxZs .
Hi All,
Please correct me if i'm wrong,
CASH_IN : Shutter will open and wait until we put some notes into tray, after notes inside shutter will automatically close. XfsExecuteCommand cmdCashIn = new XfsExecuteCommand(
cimService, CimExecuteCommand.CASH_IN, cashInStart3);
WFSResult wfsResultCashIn = null;
try {
wfsResultCashIn = cmdCashIn.call();
Shutter successfully open and close but cannot get result from 'wfsResultCashIn', looks like stuck here while debug.
OPEN_SHUTTER - CLOSE_SHUTTER Shutter will open if execute OPEN_SHUTTER and will close if we execute other command CLOSE_SHUTTER (not automatically when finish put notes inside shutter).
Regards, Azda Firmansyah